KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > gargoylesoftware > htmlunit > html > HtmlSelect


1 /*
2  * Copyright (c) 2002, 2005 Gargoyle Software Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice,
8  * this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation
11  * and/or other materials provided with the distribution.
12  * 3. The end-user documentation included with the redistribution, if any, must
13  * include the following acknowledgment:
14  *
15  * "This product includes software developed by Gargoyle Software Inc.
16  * (http://www.GargoyleSoftware.com/)."
17  *
18  * Alternately, this acknowledgment may appear in the software itself, if
19  * and wherever such third-party acknowledgments normally appear.
20  * 4. The name "Gargoyle Software" must not be used to endorse or promote
21  * products derived from this software without prior written permission.
22  * For written permission, please contact info@GargoyleSoftware.com.
23  * 5. Products derived from this software may not be called "HtmlUnit", nor may
24  * "HtmlUnit" appear in their name, without prior written permission of
25  * Gargoyle Software Inc.
26  *
27  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
28  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
29  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
30  * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
33  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
36  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  */

38 package com.gargoylesoftware.htmlunit.html;
39
40 import java.util.ArrayList JavaDoc;
41 import java.util.Collections JavaDoc;
42 import java.util.Iterator JavaDoc;
43 import java.util.List JavaDoc;
44 import java.util.Map JavaDoc;
45
46 import com.gargoylesoftware.htmlunit.Assert;
47 import com.gargoylesoftware.htmlunit.ElementNotFoundException;
48 import com.gargoylesoftware.htmlunit.KeyValuePair;
49 import com.gargoylesoftware.htmlunit.Page;
50
51
52 /**
53  * Wrapper for the html element "select"
54  *
55  * @version $Revision: 100 $
56  * @author <a HREF="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
57  * @author <a HREF="mailto:gudujarlson@sf.net">Mike J. Bresnahan</a>
58  * @author David K. Taylor
59  * @author <a HREF="mailto:cse@dynabean.de">Christian Sell</a>
60  * @author David D. Kilzer
61  * @author Marc Guillemot
62  */

63 public class HtmlSelect extends FocusableElement implements DisabledElement, SubmittableElement {
64
65     /** the HTML tag represented by this element */
66     public static final String JavaDoc TAG_NAME = "select";
67
68     private String JavaDoc[] fakeSelectedValues_;
69
70
71     /**
72      * Create an instance
73      *
74      * @param page The page that contains this element
75      * @param attributes the initial attributes
76      */

77     public HtmlSelect( final HtmlPage page, final Map JavaDoc attributes ) {
78         super( page, attributes );
79     }
80
81     /**
82      * @return the HTML tag name
83      */

84     public String JavaDoc getTagName() {
85         return TAG_NAME;
86     }
87
88     /**
89      * Return a List containing all of the currently selected options. The following special
90      * conditions can occur if the element is in single select mode:
91      * <ul>
92      * <li>if multiple options are errouneously selected, the last one is returned</li>
93      * <li>if no options are selected, the first one is returned</li>
94      * </ul>
95      *
96      * @return See above
97      */

98     public List JavaDoc getSelectedOptions() {
99         List JavaDoc result;
100
101         if(isMultipleSelectEnabled()) {
102             result = new ArrayList JavaDoc();
103
104             final DescendantElementsIterator iterator = new DescendantElementsIterator();
105             while(iterator.hasNext()) {
106                 final HtmlElement element = iterator.nextElement();
107                 if(element instanceof HtmlOption && ((HtmlOption)element).isSelected()) {
108                     result.add(element);
109                 }
110             }
111         }
112         else {
113             result = new ArrayList JavaDoc(1);
114
115             HtmlOption firstOption = null;
116             HtmlOption lastOption = null;
117
118             final DescendantElementsIterator iterator = new DescendantElementsIterator();
119             while(iterator.hasNext()) {
120                 final HtmlElement element = iterator.nextElement();
121                 if(element instanceof HtmlOption) {
122                     HtmlOption option = (HtmlOption)element;
123                     if(firstOption == null) {
124                         firstOption = option; //remember in case we need it
125
}
126                     if(option.isSelected()) {
127                         lastOption = option;
128                     }
129                 }
130             }
131             if(lastOption != null) {
132                 result.add(lastOption);
133             }
134             else {
135                 int theSize;
136                 try {
137                     theSize = Integer.parseInt(getSizeAttribute());
138                 }
139                 catch (final NumberFormatException JavaDoc e) {
140                     // Differet browsers have different (and odd) tolerances for invalid
141
// size attributes so we'll just assume anything invalid is "1"
142
theSize = 1;
143                 }
144                 if (theSize <= 1) {
145                     result.add(firstOption);
146                 }
147             }
148             return result;
149         }
150
151         return Collections.unmodifiableList( result );
152     }
153
154
155     /**
156      * Return a List containing all the options
157      *
158      * @return See above
159      * @see #getOptions
160      * @deprecated Use {@link #getOptions} instead.
161      */

162     public List JavaDoc getAllOptions() {
163         return getOptions();
164     }
165     
166     /**
167      * Return a List containing all the options
168      *
169      * @return See above
170      */

171     public List JavaDoc getOptions() {
172         final List JavaDoc elementList = getHtmlElementsByTagName( "option" );
173         return Collections.unmodifiableList( elementList );
174     }
175
176
177     /**
178      * Return the indexed option.
179      *
180      * @param index The index
181      * @return The option specified by the index
182      */

183     public HtmlOption getOption( final int index ) {
184
185         final List JavaDoc elementList = getHtmlElementsByTagName( "option" );
186         return (HtmlOption) elementList.get( index );
187     }
188
189
190     /**
191      * Return the number of options
192      * @return The number of options
193      */

194     public int getOptionSize() {
195
196         final List JavaDoc elementList = getHtmlElementsByTagName( "option" );
197         return elementList.size();
198     }
199
200
201     /**
202      * Remove options by reducing the "length" property. This has no
203      * effect if the length is set to the same or greater.
204      * @param newLength The new length property value
205      */

206     public void setOptionSize( final int newLength ) {
207         final List JavaDoc elementList = getHtmlElementsByTagName( "option" );
208
209         for(int i=elementList.size()-1; i >= newLength; i--) {
210             ((HtmlElement)elementList.get(i)).remove();
211         }
212     }
213
214
215     /**
216      * Remove an option at the given index.
217      * @param index The index of the option to remove
218      */

219     public void removeOption( final int index ) {
220         final ChildElementsIterator iterator = new ChildElementsIterator();
221         for(int i=0; iterator.hasNext(); i++) {
222             final HtmlElement element = iterator.nextElement();
223             if(i == index) {
224                 element.remove();
225                 return;
226             }
227         }
228     }
229
230
231     /**
232      * Replace an option at the given index with a new option.
233      * @param index The index of the option to remove
234      * @param newOption The new option to replace to indexed option
235      */

236     public void replaceOption( final int index, final HtmlOption newOption ) {
237
238         final ChildElementsIterator iterator = new ChildElementsIterator();
239         for(int i=0; iterator.hasNext(); i++) {
240             final HtmlElement element = iterator.nextElement();
241             if(i == index) {
242                 element.replace(newOption);
243                 return;
244             }
245         }
246     }
247
248
249     /**
250      * Add a new option at the end.
251      * @param newOption The new option to add
252      */

253     public void appendOption( final HtmlOption newOption ) {
254         appendChild( newOption ) ;
255     }
256
257
258     /**
259      * Set the "selected" state of the specified option. If this "select" is
260      * single select then calling this will deselect all other options <p>
261      *
262      * Only options that are actually in the document may be selected. If you
263      * need to select an option that really isn't there (ie testing error
264      * cases) then use {@link #fakeSelectedAttribute(String)} or {@link
265      * #fakeSelectedAttribute(String[])} instead.
266      *
267      * @param isSelected true if the option is to become selected
268      * @param optionValue The value of the option that is to change
269      * @return The page that occupies this window after this change is made. It
270      * may be the same window or it may be a freshly loaded one.
271      */

272     public Page setSelectedAttribute( final String JavaDoc optionValue, final boolean isSelected ) {
273         try {
274             return setSelectedAttribute( getOptionByValue(optionValue), isSelected );
275         }
276         catch( final ElementNotFoundException e ) {
277             throw new IllegalArgumentException JavaDoc("No option found with value: " + optionValue);
278         }
279     }
280
281     /**
282      * Set the "selected" state of the specified option. If this "select" is
283      * single select then calling this will deselect all other options <p>
284      *
285      * Only options that are actually in the document may be selected. If you
286      * need to select an option that really isn't there (ie testing error
287      * cases) then use {@link #fakeSelectedAttribute(String)} or {@link
288      * #fakeSelectedAttribute(String[])} instead.
289      *
290      * @param isSelected true if the option is to become selected
291      * @param selectedOption The value of the option that is to change
292      * @return The page that occupies this window after this change is made. It
293      * may be the same window or it may be a freshly loaded one.
294      */

295     public Page setSelectedAttribute( final HtmlOption selectedOption, final boolean isSelected ) {
296         if( isMultipleSelectEnabled() ) {
297             setSelected( selectedOption, isSelected );
298         }
299         else {
300             final Iterator JavaDoc iterator = getAllOptions().iterator();
301             while( iterator.hasNext() ) {
302                 final HtmlOption option = ( HtmlOption )iterator.next();
303                 setSelected(option, option == selectedOption && isSelected );
304             }
305         }
306
307         return getPage().executeOnChangeHandlerIfAppropriate(this);
308     }
309
310
311     /**
312      * Set the selected value to be something that was not originally contained
313      * in the document.
314      *
315      * @param optionValue The value of the new "selected" option
316      */

317     public void fakeSelectedAttribute( final String JavaDoc optionValue ) {
318         Assert.notNull( "optionValue", optionValue );
319         fakeSelectedAttribute( new String JavaDoc[]{optionValue} );
320     }
321
322
323     /**
324      * Set the selected values to be something that were not originally
325      * contained in the document.
326      *
327      * @param optionValues The values of the new "selected" options
328      */

329     public void fakeSelectedAttribute( final String JavaDoc optionValues[] ) {
330         Assert.notNull( "optionValues", optionValues );
331         fakeSelectedValues_ = optionValues;
332     }
333
334
335     private void setSelected(final HtmlOption option, final boolean isSelected ) {
336         if( isSelected ) {
337             option.setAttributeValue( "selected", "selected" );
338         }
339         else {
340             option.removeAttribute( "selected" );
341         }
342     }
343
344
345     /**
346      * Return an array of KeyValuePairs that are the values that will be sent
347      * back to the server whenever the current form is submitted.<p>
348      *
349      * THIS METHOD IS INTENDED FOR THE USE OF THE FRAMEWORK ONLY AND SHOULD NOT
350      * BE USED BY CONSUMERS OF HTMLUNIT. USE AT YOUR OWN RISK.
351      *
352      * @return See above
353      */

354     public KeyValuePair[] getSubmitKeyValuePairs() {
355         final String JavaDoc name = getNameAttribute();
356         final KeyValuePair[] pairs;
357
358         if( fakeSelectedValues_ == null ) {
359             final List JavaDoc selectedOptions = getSelectedOptions();
360             final int optionCount = selectedOptions.size();
361
362             pairs = new KeyValuePair[optionCount];
363
364             for( int i = 0; i < optionCount; i++ ) {
365                 final HtmlOption option = ( HtmlOption )selectedOptions.get( i );
366                 pairs[i] = new KeyValuePair( name, option.getValue() );
367             }
368         }
369         else {
370             final List JavaDoc pairsList = new ArrayList JavaDoc();
371             for( int i = 0; i < fakeSelectedValues_.length; i++ ) {
372                 if (fakeSelectedValues_[i].length() > 0) {
373                     pairsList.add(new KeyValuePair( name, fakeSelectedValues_[i] ));
374                 }
375             }
376             pairs = (KeyValuePair[]) pairsList.toArray(new KeyValuePair[pairsList.size()]);
377         }
378         return pairs;
379     }
380
381
382     /**
383      * Return the value of this element to what it was at the time the page was loaded.
384      */

385     public void reset() {
386         final Iterator JavaDoc iterator = getAllOptions().iterator();
387         while( iterator.hasNext() ) {
388             final HtmlOption option = (HtmlOption)iterator.next();
389             option.reset();
390         }
391     }
392
393
394     /**
395      * Return true if this select is using "multiple select"
396      *
397      * @return See above
398      */

399     public boolean isMultipleSelectEnabled() {
400         return getAttributeValue( "multiple" ) != ATTRIBUTE_NOT_DEFINED;
401     }
402
403
404     /**
405      * Return the HtmlOption object that corresponds to the specified value
406      *
407      * @param value The value to search by
408      * @return See above
409      * @exception ElementNotFoundException If a particular xml element could
410      * not be found in the dom model
411      */

412     public HtmlOption getOptionByValue( final String JavaDoc value )
413         throws ElementNotFoundException {
414         Assert.notNull("value", value);
415
416         return ( HtmlOption )getOneHtmlElementByAttribute( "option", "value", value );
417     }
418
419
420     /**
421      * Return a text representation of this element that represents what would
422      * be visible to the user if this page was shown in a web browser. For
423      * example, a select element would return the currently selected value as
424      * text
425      *
426      * @return The element as text
427      */

428     public String JavaDoc asText() {
429
430         final List JavaDoc options;
431         if( isMultipleSelectEnabled() ) {
432             options = getAllOptions();
433         }
434         else {
435             options = getSelectedOptions();
436         }
437
438         boolean isFirstTimeThrough = true;
439         final StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
440
441         final Iterator JavaDoc iterator = options.iterator();
442         while( iterator.hasNext() ) {
443             if( isFirstTimeThrough == true ) {
444                 isFirstTimeThrough = false;
445             }
446             else {
447                 buffer.append( "\n" );
448             }
449
450             final HtmlOption currentOption = ( HtmlOption )iterator.next();
451             if( currentOption != null) {
452                 buffer.append( currentOption.asText() );
453             }
454         }
455
456         return buffer.toString();
457     }
458
459
460     /**
461      * Return the value of the attribute "name". Refer to the <a
462      * HREF='http://www.w3.org/TR/html401/'>HTML 4.01</a> documentation for
463      * details on the use of this attribute.
464      *
465      * @return The value of the attribute "name" or an empty string if that
466      * attribute isn't defined.
467      */

468     public final String JavaDoc getNameAttribute() {
469         return getAttributeValue( "name" );
470     }
471
472
473     /**
474      * Return the value of the attribute "size". Refer to the <a
475      * HREF='http://www.w3.org/TR/html401/'>HTML 4.01</a> documentation for
476      * details on the use of this attribute.
477      *
478      * @return The value of the attribute "size" or an empty string if that
479      * attribute isn't defined.
480      */

481     public final String JavaDoc getSizeAttribute() {
482         return getAttributeValue( "size" );
483     }
484
485
486     /**
487      * Return the value of the attribute "multiple". Refer to the <a
488      * HREF='http://www.w3.org/TR/html401/'>HTML 4.01</a> documentation for
489      * details on the use of this attribute.
490      *
491      * @return The value of the attribute "multiple" or an empty string if that
492      * attribute isn't defined.
493      */

494     public final String JavaDoc getMultipleAttribute() {
495         return getAttributeValue( "multiple" );
496     }
497
498
499     /**
500      * Return the value of the attribute "disabled". Refer to the <a
501      * HREF='http://www.w3.org/TR/html401/'>HTML 4.01</a> documentation for
502      * details on the use of this attribute.
503      *
504      * @return The value of the attribute "disabled" or an empty string if that
505      * attribute isn't defined.
506      */

507     public final String JavaDoc getDisabledAttribute() {
508         return getAttributeValue( "disabled" );
509     }
510
511     /**
512      * Return true if the disabled attribute is set for this element.
513      *
514      * @return Return true if this element is disabled.
515      */

516     public final boolean isDisabled() {
517         return isAttributeDefined( "disabled" );
518     }
519
520     /**
521      * Return the value of the attribute "tabindex". Refer to the <a
522      * HREF='http://www.w3.org/TR/html401/'>HTML 4.01</a> documentation for
523      * details on the use of this attribute.
524      *
525      * @return The value of the attribute "tabindex" or an empty string if that
526      * attribute isn't defined.
527      */

528     public final String JavaDoc getTabIndexAttribute() {
529         return getAttributeValue( "tabindex" );
530     }
531
532
533     /**
534      * Return the value of the attribute "onfocus". Refer to the <a
535      * HREF='http://www.w3.org/TR/html401/'>HTML 4.01</a> documentation for
536      * details on the use of this attribute.
537      *
538      * @return The value of the attribute "onfocus" or an empty string if that
539      * attribute isn't defined.
540      */

541     public final String JavaDoc getOnFocusAttribute() {
542         return getAttributeValue( "onfocus" );
543     }
544
545
546     /**
547      * Return the value of the attribute "onblur". Refer to the <a
548      * HREF='http://www.w3.org/TR/html401/'>HTML 4.01</a> documentation for
549      * details on the use of this attribute.
550      *
551      * @return The value of the attribute "onblur" or an empty string if that
552      * attribute isn't defined.
553      */

554     public final String JavaDoc getOnBlurAttribute() {
555         return getAttributeValue( "onblur" );
556     }
557
558
559     /**
560      * Return the value of the attribute "onchange". Refer to the <a
561      * HREF='http://www.w3.org/TR/html401/'>HTML 4.01</a> documentation for
562      * details on the use of this attribute.
563      *
564      * @return The value of the attribute "onchange" or an empty string if that
565      * attribute isn't defined.
566      */

567     public final String JavaDoc getOnChangeAttribute() {
568         return getAttributeValue( "onchange" );
569     }
570 }
571
Popular Tags