View Javadoc

1   /*
2    * $Id: Submit.java 451544 2006-09-30 05:38:02Z mrdon $
3    *
4    * Copyright 2006 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.struts2.components;
19  
20  import javax.servlet.http.HttpServletRequest;
21  import javax.servlet.http.HttpServletResponse;
22  
23  import com.opensymphony.xwork2.util.ValueStack;
24  
25  /***
26   * <!-- START SNIPPET: javadoc -->
27   * Render a submit button. The submit tag is used together with the form tag to provide asynchronous form submissions.
28   * The submit can have three different types of rendering:
29   * <ul>
30   * <li>input: renders as html &lt;input type="submit"...&gt;</li>
31   * <li>image: renders as html &lt;input type="image"...&gt;</li>
32   * <li>button: renders as html &lt;button type="submit"...&gt;</li>
33   * </ul>
34   * Please note that the button type has advantages by adding the possibility to seperate the submitted value from the
35   * text shown on the button face, but has issues with Microsoft Internet Explorer at least up to 6.0
36   * <!-- END SNIPPET: javadoc -->
37   *
38   * <p/> <b>Examples</b>
39   *
40   * <pre>
41   * <!-- START SNIPPET: example -->
42   * &lt;s:submit value="%{'Submit'}" /&gt;
43   * <!-- END SNIPPET: example -->
44   * </pre>
45   * 
46   * <pre>
47   * <!-- START SNIPPET: example2 -->
48   * Render an image submit:
49   * &lt;s:submit type="image" value="%{'Submit'}" label="Submit the form" src="submit.gif"/&gt;
50   * <!-- END SNIPPET: example2 -->
51   * </pre>
52   *
53   * <pre>
54   * <!-- START SNIPPET: example3 -->
55   * Render an button submit:
56   * &lt;s:submit type="button" value="%{'Submit'}" label="Submit the form"/&gt;
57   * <!-- END SNIPPET: example3 -->
58   * </pre>
59   *
60   * <!-- START SNIPPET: ajaxJavadoc -->
61   * <B>THE FOLLOWING IS ONLY VALID WHEN AJAX IS CONFIGURED</B>
62   * <ul>
63   * 		<li>resultDivId</li>
64   * 		<li>notifyTopics</li>
65   * 		<li>onLoadJS</li>
66   * 		<li>preInvokeJS</li>
67   * </ul>
68   * The remote form has three basic modes of use, using the resultDivId, 
69   * the notifyTopics, or the onLoadJS. You can mix and match any combination of 
70   * them to get your desired result. All of these examples are contained in the 
71   * Ajax example webapp. Lets go through some scenarios to see how you might use it:
72   * <!-- END SNIPPET: ajaxJavadoc -->
73   * 
74   * <!-- START SNIPPET: ajxExDescription1 -->
75   * Show the results in another div. If you want your results to be shown in 
76   * a div, use the resultDivId where the id is the id of the div you want them 
77   * shown in. This is an inner HTML approah. Your results get jammed into 
78   * the div for you. Here is a sample of this approach:
79   * <!-- END SNIPPET: ajxExDescription1 -->
80   * 
81   * <pre>
82   * <!-- START SNIPPET: ajxExample1 -->
83   * Remote form replacing another div:
84   * &lt;div id='two' style="border: 1px solid yellow;"&gt;Initial content&lt;/div&gt;
85   * &lt;s:form
86   *       id='theForm2'
87   *       cssStyle="border: 1px solid green;"
88   *       action='/AjaxRemoteForm.action'
89   *       method='post'
90   *       theme="ajax"&gt;
91   *
92   *   &lt;input type='text' name='data' value='Struts User' /&gt;
93   *   &lt;s:submit value="GO2" theme="ajax" resultDivId="two" /&gt;
94   *
95   * &lt;/s:form &gt;
96   * <!-- END SNIPPET: ajxExample1 -->
97   * </pre>
98   * 
99   * 
100  * <!-- START SNIPPET: ajxExDescription2 -->
101  * Notify other controls(divs) of a change. Using an pub-sub model you can 
102  * notify others that your control changed and they can take the appropriate action. 
103  * Most likely they will execute some action to refresh. The notifyTopics does this 
104  * for you. You can have many topic names in a comma delimited list. 
105  * eg: notifyTopics="newPerson, dataChanged" .
106  * Here is an example of this approach:
107  * <!-- END SNIPPET: ajxExDescription2 -->
108  * 
109  * <pre>
110  * <!-- START SNIPPET: ajxExample2 -->
111  * &lt;s:form id="frm1" action="newPersonWithXMLResult" theme="ajax"  &gt;
112  *     &lt;s:textfield label="Name" name="person.name" value="person.name" size="20" required="true" /&gt;
113  *     &lt;s:submit id="submitBtn" value="Save" theme="ajax"  cssClass="primary"  notifyTopics="personUpdated, systemWorking" /&gt;
114  * &lt;/s:form &gt;
115  * 
116  * &lt;s:div href="/listPeople.action" theme="ajax" errorText="error opps"
117  *         loadingText="loading..." id="cart-body" &gt;
118  *     &lt;s:action namespace="" name="listPeople" executeResult="true" /&gt;
119  * &lt;/s:div&gt;
120  * <!-- END SNIPPET: ajxExample2 -->
121  * </pre>
122  *
123  * <!-- START SNIPPET: ajxExDescription3 -->
124  * Massage the results with JavaScript. Say that your result returns some h
125  * appy XML and you want to parse it and do lots of cool things with it. 
126  * The way to do this is with a onLoadJS handler. Here you provide the name of
127  * a JavaScript function to be called back with the result and the event type.
128  * The only key is that you must use the variable names 'data' and 'type' when 
129  * defining the callback. For example: onLoadJS="myFancyDancyFunction(data, type)".
130  * While I talked about XML in this example, your not limited to XML, the data in 
131  * the callback will be exactly whats returned as your result.
132  * Here is an example of this approach:
133  * <!-- END SNIPPET: ajxExDescription3 -->
134  *
135  * <pre>
136  * <!-- START SNIPPET: ajxExample3 -->
137  * &lt;script language="JavaScript" type="text/javascript"&gt;
138  *     function doGreatThings(data, type) {
139  *         //Do whatever with your returned fragment... 
140  *         //Perhapps.... if xml...
141  *               var xml = dojo.xml.domUtil.createDocumentFromText(data);
142  *               var people = xml.getElementsByTagName("person");
143  *               for(var i = 0;i < people.length; i ++){
144  *                   var person = people[i];
145  *                   var name = person.getAttribute("name")
146  *                   var id = person.getAttribute("id")
147  *                   alert('Thanks dude. Person: ' + name + ' saved great!!!');
148  *               }
149  *
150  *     }
151  * &lt;/script&gt;
152  *
153  * &lt;s:form id="frm1" action="newPersonWithXMLResult" theme="ajax"  &gt;
154  *     &lt;s:textfield label="Name" name="person.name" value="person.name" size="20" required="true" /&gt;
155  *     &lt;s:submit id="submitBtn" value="Save" theme="ajax"  cssClass="primary"  onLoadJS="doGreatThings(data, type)" /&gt;
156  * &lt;/s:form&gt;
157  * <!-- END SNIPPET: ajxExample3 -->
158  * </pre>
159  *
160  * @s.tag name="submit" tld-body-content="JSP" tld-tag-class="org.apache.struts2.views.jsp.ui.SubmitTag"
161  * description="Render a submit button"
162  */
163 public class Submit extends FormButton {
164     final public static String TEMPLATE = "submit";
165 
166     protected String resultDivId;
167     protected String onLoadJS;
168     protected String notifyTopics;
169     protected String listenTopics;
170     protected String preInvokeJS;
171     protected String src;
172 
173     public Submit(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
174         super(stack, request, response);
175     }
176 
177     protected String getDefaultTemplate() {
178         return TEMPLATE;
179     }
180 
181     public void evaluateParams() {
182     	if (value == null) {
183             value = "Submit";
184         }
185     	super.evaluateParams();
186     }
187     
188     public void evaluateExtraParams() {
189     	super.evaluateExtraParams();
190 
191        /* if (value == null) {
192             value = "Submit";
193         }*/
194 
195         //super.evaluateParams();
196 
197         if (null != src) {
198             addParameter("src", findString(src));
199         }
200 
201         if (null != resultDivId) {
202             addParameter("resultDivId", findString(resultDivId));
203         }
204 
205         if (null != onLoadJS) {
206             addParameter("onLoadJS", findString(onLoadJS));
207         }
208 
209         if (null != notifyTopics) {
210             addParameter("notifyTopics", findString(notifyTopics));
211         }
212 
213         if (null != listenTopics) {
214             addParameter("listenTopics", findString(listenTopics));
215         }
216 
217         if (preInvokeJS != null) {
218             addParameter("preInvokeJS", findString(preInvokeJS));
219         }
220 
221     }
222 
223     /***
224      * Indicate whether the concrete button supports the type "image".
225      *
226      * @return <tt>true</tt> to indicate type image is supported.
227      */
228     protected boolean supportsImageType() {
229         return true;
230     }
231 
232     /***
233      * The id of the HTML element to place the result (this can the the form's id or any id on the page.
234      * @s.tagattribute required="false"  type="String"
235      */
236     public void setResultDivId(String resultDivId) {
237         this.resultDivId = resultDivId;
238     }
239 
240     /***
241      * Javascript code that will be executed after the form has been submitted. The format is onLoadJS='yourMethodName(data,type)'. NOTE: the words data and type must be left like that if you want the event type and the returned data.
242      * @s.tagattribute required="false" type="String"
243      */
244     public void setOnLoadJS(String onLoadJS) {
245         this.onLoadJS = onLoadJS;
246     }
247 
248     /***
249      * Topic names to post an event to after the form has been submitted.
250      * @s.tagattribute required="false" type="String"
251      */
252     public void setNotifyTopics(String notifyTopics) {
253         this.notifyTopics = notifyTopics;
254     }
255 
256     /***
257      * Set listenTopics attribute.
258      * @s.tagattribute required="false" type="String"
259      */
260     public void setListenTopics(String listenTopics) {
261         this.listenTopics = listenTopics;
262     }
263 
264     /***
265      * Javascript code that will be executed before invokation. The format is preInvokeJS='yourMethodName(data,type)'.
266      * @s.tagattribute required="false" type="String"
267      */
268     public void setPreInvokeJS(String preInvokeJS) {
269         this.preInvokeJS = preInvokeJS;
270     }
271 
272     /***
273      * Supply a submit button text apart from submit value. Will have no effect for <i>input</i> type submit, since button text will always be the value parameter. For the type <i>image</i>, alt parameter will be set to this value.
274      * @s.tagattribute required="false"
275      */
276     public void setLabel(String label) {
277         super.setLabel(label);
278     }
279 
280     /***
281      * Supply an image src for <i>image</i> type submit button. Will have no effect for types <i>input</i> and <i>button</i>.
282      * @s.tagattribute required="false"
283      */
284     public void setSrc(String src) {
285         this.src = src;
286     }
287 }