001: /*
002: * Copyright (c) 2002-2008 Gargoyle Software Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * 1. Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: * 2. Redistributions in binary form must reproduce the above copyright notice,
010: * this list of conditions and the following disclaimer in the documentation
011: * and/or other materials provided with the distribution.
012: * 3. The end-user documentation included with the redistribution, if any, must
013: * include the following acknowledgment:
014: *
015: * "This product includes software developed by Gargoyle Software Inc.
016: * (http://www.GargoyleSoftware.com/)."
017: *
018: * Alternately, this acknowledgment may appear in the software itself, if
019: * and wherever such third-party acknowledgments normally appear.
020: * 4. The name "Gargoyle Software" must not be used to endorse or promote
021: * products derived from this software without prior written permission.
022: * For written permission, please contact info@GargoyleSoftware.com.
023: * 5. Products derived from this software may not be called "HtmlUnit", nor may
024: * "HtmlUnit" appear in their name, without prior written permission of
025: * Gargoyle Software Inc.
026: *
027: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
028: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
029: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
030: * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
031: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
032: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
033: * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
034: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
035: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
036: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037: */
038: package com.gargoylesoftware.htmlunit.html;
039:
040: import java.io.IOException;
041: import java.util.Map;
042:
043: import com.gargoylesoftware.htmlunit.Assert;
044: import com.gargoylesoftware.htmlunit.ElementNotFoundException;
045: import com.gargoylesoftware.htmlunit.KeyValuePair;
046: import com.gargoylesoftware.htmlunit.Page;
047: import com.gargoylesoftware.htmlunit.ScriptResult;
048: import com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine;
049: import com.gargoylesoftware.htmlunit.javascript.host.Event;
050:
051: /**
052: * Wrapper for the html element "input"
053: *
054: * @version $Revision: 2132 $
055: * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
056: * @author David K. Taylor
057: * @author <a href="mailto:cse@dynabean.de">Christian Sell</a>
058: * @author David D. Kilzer
059: * @author Marc Guillemot
060: * @author Daniel Gredler
061: * @author Ahmed Ashour
062: */
063: public abstract class HtmlInput extends FocusableElement implements
064: DisabledElement, SubmittableElement {
065:
066: /** the HTML tag represented by this element */
067: public static final String TAG_NAME = "input";
068:
069: private String defaultValue_;
070:
071: /**
072: * Create an instance
073: *
074: * @param page The page that contains this element
075: * @param attributes the initial attributes
076: */
077: public HtmlInput(final HtmlPage page, final Map attributes) {
078: this (null, TAG_NAME, page, attributes);
079: }
080:
081: /**
082: * Create an instance
083: *
084: * @param namespaceURI the URI that identifies an XML namespace.
085: * @param qualifiedName The qualified name of the element type to instantiate
086: * @param page The page that contains this element
087: * @param attributes the initial attributes
088: */
089: public HtmlInput(final String namespaceURI,
090: final String qualifiedName, final HtmlPage page,
091: final Map attributes) {
092: super (namespaceURI, qualifiedName, page, attributes);
093: defaultValue_ = getValueAttribute();
094: }
095:
096: /**
097: * Set the content of the "value" attribute, executing onchange handlers if appropriate.
098: * @param newValue The new content
099: * @return the page that occupies this window after this value is set.
100: * It may be the same window or it may be a freshly loaded one.
101: */
102: public Page setValueAttribute(final String newValue) {
103: Assert.notNull("newValue", newValue);
104: setAttributeValue("value", newValue);
105:
106: return executeOnChangeHandlerIfAppropriate(this );
107: }
108:
109: /**
110: * Return an array of KeyValuePairs that are the values that will be sent
111: * back to the server whenever the current form is submitted.<p>
112: *
113: * THIS METHOD IS INTENDED FOR THE USE OF THE FRAMEWORK ONLY AND SHOULD NOT
114: * BE USED BY CONSUMERS OF HTMLUNIT. USE AT YOUR OWN RISK.
115: *
116: * @return See above
117: */
118: public KeyValuePair[] getSubmitKeyValuePairs() {
119: return new KeyValuePair[] { new KeyValuePair(
120: getNameAttribute(), getValueAttribute()) };
121: }
122:
123: /**
124: * {@inheritDoc}
125: */
126: public String asText() {
127: return getValueAttribute();
128: }
129:
130: /**
131: * Return the value of the attribute "type". Refer to the
132: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
133: * documentation for details on the use of this attribute.
134: *
135: * @return The value of the attribute "type"
136: * or an empty string if that attribute isn't defined.
137: */
138: public final String getTypeAttribute() {
139: return getAttributeValue("type");
140: }
141:
142: /**
143: * Return the value of the attribute "name". Refer to the
144: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
145: * documentation for details on the use of this attribute.
146: *
147: * @return The value of the attribute "name"
148: * or an empty string if that attribute isn't defined.
149: */
150: public final String getNameAttribute() {
151: return getAttributeValue("name");
152: }
153:
154: /**
155: * <p>Return the value of the attribute "value". Refer to the
156: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
157: * documentation for details on the use of this attribute.</p>
158: *
159: * @return The value of the attribute "value" or an empty string if that
160: * attribute isn't defined
161: */
162: public final String getValueAttribute() {
163: return getAttributeValue("value");
164: }
165:
166: /**
167: * Return the value of the attribute "checked". Refer to the
168: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
169: * documentation for details on the use of this attribute.
170: *
171: * @return The value of the attribute "checked"
172: * or an empty string if that attribute isn't defined.
173: */
174: public final String getCheckedAttribute() {
175: return getAttributeValue("checked");
176: }
177:
178: /**
179: * Return the value of the attribute "disabled". Refer to the
180: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
181: * documentation for details on the use of this attribute.
182: *
183: * @return The value of the attribute "disabled"
184: * or an empty string if that attribute isn't defined.
185: */
186: public final String getDisabledAttribute() {
187: return getAttributeValue("disabled");
188: }
189:
190: /**
191: * Return true if the disabled attribute is set for this element.
192: * @return Return true if this is disabled.
193: */
194: public final boolean isDisabled() {
195: return isAttributeDefined("disabled");
196: }
197:
198: /**
199: * Return the value of the attribute "readonly". Refer to the
200: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
201: * documentation for details on the use of this attribute.
202: *
203: * @return The value of the attribute "readonly"
204: * or an empty string if that attribute isn't defined.
205: */
206: public final String getReadOnlyAttribute() {
207: return getAttributeValue("readonly");
208: }
209:
210: /**
211: * Return the value of the attribute "size". Refer to the
212: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
213: * documentation for details on the use of this attribute.
214: *
215: * @return The value of the attribute "size"
216: * or an empty string if that attribute isn't defined.
217: */
218: public final String getSizeAttribute() {
219: return getAttributeValue("size");
220: }
221:
222: /**
223: * Return the value of the attribute "maxlength". Refer to the
224: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
225: * documentation for details on the use of this attribute.
226: *
227: * @return The value of the attribute "maxlength"
228: * or an empty string if that attribute isn't defined.
229: */
230: public final String getMaxLengthAttribute() {
231: return getAttributeValue("maxlength");
232: }
233:
234: /**
235: * Return the value of the attribute "src". Refer to the
236: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
237: * documentation for details on the use of this attribute.
238: *
239: * @return The value of the attribute "src"
240: * or an empty string if that attribute isn't defined.
241: */
242: public final String getSrcAttribute() {
243: return getAttributeValue("src");
244: }
245:
246: /**
247: * Return the value of the attribute "alt". Refer to the
248: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
249: * documentation for details on the use of this attribute.
250: *
251: * @return The value of the attribute "alt"
252: * or an empty string if that attribute isn't defined.
253: */
254: public final String getAltAttribute() {
255: return getAttributeValue("alt");
256: }
257:
258: /**
259: * Return the value of the attribute "usemap". Refer to the
260: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
261: * documentation for details on the use of this attribute.
262: *
263: * @return The value of the attribute "usemap"
264: * or an empty string if that attribute isn't defined.
265: */
266: public final String getUseMapAttribute() {
267: return getAttributeValue("usemap");
268: }
269:
270: /**
271: * Return the value of the attribute "tabindex". Refer to the
272: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
273: * documentation for details on the use of this attribute.
274: *
275: * @return The value of the attribute "tabindex"
276: * or an empty string if that attribute isn't defined.
277: */
278: public final String getTabIndexAttribute() {
279: return getAttributeValue("tabindex");
280: }
281:
282: /**
283: * Return the value of the attribute "accesskey". Refer to the
284: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
285: * documentation for details on the use of this attribute.
286: *
287: * @return The value of the attribute "accesskey"
288: * or an empty string if that attribute isn't defined.
289: */
290: public final String getAccessKeyAttribute() {
291: return getAttributeValue("accesskey");
292: }
293:
294: /**
295: * Return the value of the attribute "onfocus". Refer to the
296: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
297: * documentation for details on the use of this attribute.
298: *
299: * @return The value of the attribute "onfocus"
300: * or an empty string if that attribute isn't defined.
301: */
302: public final String getOnFocusAttribute() {
303: return getAttributeValue("onfocus");
304: }
305:
306: /**
307: * Return the value of the attribute "onblur". Refer to the
308: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
309: * documentation for details on the use of this attribute.
310: *
311: * @return The value of the attribute "onblur"
312: * or an empty string if that attribute isn't defined.
313: */
314: public final String getOnBlurAttribute() {
315: return getAttributeValue("onblur");
316: }
317:
318: /**
319: * Return the value of the attribute "onselect". Refer to the
320: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
321: * documentation for details on the use of this attribute.
322: *
323: * @return The value of the attribute "onselect"
324: * or an empty string if that attribute isn't defined.
325: */
326: public final String getOnSelectAttribute() {
327: return getAttributeValue("onselect");
328: }
329:
330: /**
331: * Return the value of the attribute "onchange". Refer to the
332: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
333: * documentation for details on the use of this attribute.
334: *
335: * @return The value of the attribute "onchange"
336: * or an empty string if that attribute isn't defined.
337: */
338: public final String getOnChangeAttribute() {
339: return getAttributeValue("onchange");
340: }
341:
342: /**
343: * Return the value of the attribute "accept". Refer to the
344: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
345: * documentation for details on the use of this attribute.
346: *
347: * @return The value of the attribute "accept"
348: * or an empty string if that attribute isn't defined.
349: */
350: public final String getAcceptAttribute() {
351: return getAttributeValue("accept");
352: }
353:
354: /**
355: * Return the value of the attribute "align". Refer to the
356: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
357: * documentation for details on the use of this attribute.
358: *
359: * @return The value of the attribute "align"
360: * or an empty string if that attribute isn't defined.
361: */
362: public final String getAlignAttribute() {
363: return getAttributeValue("align");
364: }
365:
366: /**
367: * {@inheritDoc}
368: * @see SubmittableElement#reset()
369: */
370: public void reset() {
371: setValueAttribute(defaultValue_);
372: }
373:
374: /**
375: * {@inheritDoc} Also sets the value attribute when emulating Netscape browsers.
376: * @see SubmittableElement#setDefaultValue(String)
377: * @see HtmlFileInput#setDefaultValue(String)
378: */
379: public void setDefaultValue(final String defaultValue) {
380: final boolean modifyValue = getPage().getWebClient()
381: .getBrowserVersion().isNetscape();
382: setDefaultValue(defaultValue, modifyValue);
383: }
384:
385: /**
386: * Sets the default value, optionally also modifying the current value.
387: * @param defaultValue The new default value.
388: * @param modifyValue Whether or not to set the current value to the default value.
389: */
390: protected void setDefaultValue(final String defaultValue,
391: final boolean modifyValue) {
392: defaultValue_ = defaultValue;
393: if (modifyValue) {
394: setValueAttribute(defaultValue);
395: }
396: }
397:
398: /**
399: * {@inheritDoc}
400: * @see SubmittableElement#getDefaultValue()
401: */
402: public String getDefaultValue() {
403: return defaultValue_;
404: }
405:
406: /**
407: * {@inheritDoc} The default implementation is empty; only checkboxes and radio buttons
408: * really care what the default checked value is.
409: * @see SubmittableElement#setDefaultChecked(boolean)
410: * @see HtmlRadioButtonInput#setDefaultChecked(boolean)
411: * @see HtmlCheckBoxInput#setDefaultChecked(boolean)
412: */
413: public void setDefaultChecked(final boolean defaultChecked) {
414: // Empty.
415: }
416:
417: /**
418: * {@inheritDoc} The default implementation returns <tt>false</tt>; only checkboxes and
419: * radio buttons really care what the default checked value is.
420: * @see SubmittableElement#isDefaultChecked()
421: * @see HtmlRadioButtonInput#isDefaultChecked()
422: * @see HtmlCheckBoxInput#isDefaultChecked()
423: */
424: public boolean isDefaultChecked() {
425: return false;
426: }
427:
428: /**
429: * Set the "checked" attribute
430: *
431: * @param isChecked true if this element is to be selected
432: * @return The page that occupies this window after setting checked status.
433: * It may be the same window or it may be a freshly loaded one.
434: */
435: public Page setChecked(final boolean isChecked) {
436: // By default this returns the current page. Derived classes will override.
437: return getPage();
438: }
439:
440: /**
441: * Return true if this element is currently selected
442: *
443: * @return See above
444: */
445: public boolean isChecked() {
446: return isAttributeDefined("checked");
447: }
448:
449: /**
450: * Simulate clicking this input with a pointing device. The x and y coordinates
451: * of the pointing device will be sent to the server.
452: *
453: * @param x The x coordinate of the pointing device at the time of clicking
454: * @param y The y coordinate of the pointing device at the time of clicking
455: * @return The page that is loaded after the click has taken place.
456: * @exception IOException If an io error occurs
457: * @exception ElementNotFoundException If a particular xml element could not be found in the dom model
458: */
459: public Page click(final int x, final int y) throws IOException,
460: ElementNotFoundException {
461:
462: // By default this is no different than a click without coordinates.
463: return click();
464: }
465:
466: /**
467: * Executes the onchange script code for this element if this is appropriate.
468: * This means that the element must have an onchange script, script must be enabled
469: * and the change in the element must not have been triggered by a script.
470: *
471: * @param htmlElement The element that contains the onchange attribute.
472: * @return The page that occupies this window after this method completes. It
473: * may be this or it may be a freshly loaded page.
474: */
475: static Page executeOnChangeHandlerIfAppropriate(
476: final HtmlElement htmlElement) {
477: final HtmlPage page = htmlElement.getPage();
478:
479: final JavaScriptEngine engine = htmlElement.getPage()
480: .getWebClient().getJavaScriptEngine();
481: if (engine.isScriptRunning()) {
482: return page;
483: }
484: final ScriptResult scriptResult = htmlElement
485: .fireEvent(Event.TYPE_CHANGE);
486:
487: if (page.getWebClient().getWebWindows().contains(
488: page.getEnclosingWindow())) {
489: return page.getEnclosingWindow().getEnclosedPage(); // may be itself or a newly loaded one
490: } else if (scriptResult != null) {
491: // current window doesn't exist anymore
492: return scriptResult.getNewPage();
493: }
494:
495: return page;
496: }
497: }
|