1 38 package com.gargoylesoftware.htmlunit.html; 39 40 import java.io.IOException ; 41 import java.net.MalformedURLException ; 42 import java.net.URL ; 43 import java.util.ArrayList ; 44 import java.util.Arrays ; 45 import java.util.Collection ; 46 import java.util.Iterator ; 47 import java.util.List ; 48 import java.util.Map ; 49 50 import org.org.apache.commons.httpclient.NameValuePair; 51 import org.org.apache.commons.httpclient.util.EncodingUtil; 52 import org.apache.commons.lang.StringUtils; 53 import org.mozilla.javascript.Function; 54 import org.mozilla.javascript.Scriptable; 55 56 57 import com.gargoylesoftware.htmlunit.Assert; 58 import com.gargoylesoftware.htmlunit.ElementNotFoundException; 59 import com.gargoylesoftware.htmlunit.FormEncodingType; 60 import com.gargoylesoftware.htmlunit.KeyValuePair; 61 import com.gargoylesoftware.htmlunit.Page; 62 import com.gargoylesoftware.htmlunit.ScriptResult; 63 import com.gargoylesoftware.htmlunit.SubmitMethod; 64 import com.gargoylesoftware.htmlunit.TextUtil; 65 import com.gargoylesoftware.htmlunit.WebRequestSettings; 66 import com.gargoylesoftware.htmlunit.WebWindow; 67 68 80 public class HtmlForm extends ClickableElement { 81 82 83 public static final String TAG_NAME = "form"; 84 85 private static final Collection SUBMITTABLE_ELEMENT_NAMES = 86 Arrays.asList( new String []{"input", "button", "select", "textarea", "isindex"} ); 87 88 private KeyValuePair fakeSelectedRadioButton_ = null; 89 90 96 public HtmlForm( final HtmlPage htmlPage, final Map attributes) { 97 super(htmlPage, attributes); 98 } 99 100 103 public String getTagName() { 104 return TAG_NAME; 105 } 106 107 117 public Page submit( final String buttonName ) throws IOException , ElementNotFoundException { 118 119 final List inputList = getHtmlElementsByAttribute("input", "name", buttonName); 120 final Iterator iterator = inputList.iterator(); 121 while( iterator.hasNext() ) { 122 final HtmlInput input = (HtmlInput)iterator.next(); 123 if( input.getTypeAttribute().equals("submit")) { 124 return submit( input ); 125 } 126 } 127 128 final HtmlButton button = (HtmlButton)getOneHtmlElementByAttribute( "button", "name", buttonName ); 129 return submit( button ); 130 } 131 132 133 142 public Page submit() throws IOException { 143 return submit( ( SubmittableElement )null ); 144 } 145 146 147 156 Page submit( final SubmittableElement submitElement ) throws IOException { 157 158 final String action = getActionAttribute(); 159 final HtmlPage htmlPage = getPage(); 160 if( htmlPage.getWebClient().isJavaScriptEnabled() ) { 161 if( submitElement != null ) { 162 final Function onsubmit = getEventHandler("onsubmit"); 163 if (onsubmit != null 164 && htmlPage.getWebClient().isJavaScriptEnabled()) { 165 final ScriptResult scriptResult = htmlPage 166 .executeJavaScriptFunctionIfPossible(onsubmit, 167 (Scriptable) getScriptObject(), 168 new Object [0], this); 169 if (scriptResult.getJavaScriptResult() 170 .equals(Boolean.FALSE)) { 171 return scriptResult.getNewPage(); 172 } 173 } 174 } 175 176 if( TextUtil.startsWithIgnoreCase(action, "javascript:") ) { 177 return htmlPage.executeJavaScriptIfPossible( action, "Form action", false, this ).getNewPage(); 178 } 179 } 180 else { 181 if( TextUtil.startsWithIgnoreCase(action, "javascript:") ) { 182 return htmlPage; 185 } 186 } 187 188 final List parameters = getParameterListForSubmit(submitElement); 189 final SubmitMethod method = SubmitMethod.getInstance( getAttributeValue("method")); 190 191 String actionUrl = action; 192 if (SubmitMethod.GET.equals(method)) { 193 actionUrl = StringUtils.substringBefore(actionUrl, "#"); 195 196 final NameValuePair[] pairs = new NameValuePair[parameters.size()]; 197 parameters.toArray( pairs ); 198 final String queryFromFields = EncodingUtil.formUrlEncode(pairs, getPage().getPageEncoding()); 199 actionUrl = StringUtils.substringBefore(actionUrl, "?") + "?" + queryFromFields; 201 parameters.clear(); } 203 final URL url; 204 try { 205 url = htmlPage.getFullyQualifiedUrl( actionUrl ); 206 } 207 catch( final MalformedURLException e ) { 208 throw new IllegalArgumentException ( "Not a valid url: " + actionUrl ); 209 } 210 211 final WebRequestSettings settings = new WebRequestSettings(url, method); 212 settings.setRequestParameters(parameters); 213 settings.setEncodingType(FormEncodingType.getInstance( getEnctypeAttribute() )); 214 215 final WebWindow webWindow = htmlPage.getEnclosingWindow(); 216 return htmlPage.getWebClient().getPage( 217 webWindow, 218 htmlPage.getResolvedTarget(getTargetAttribute()), 219 settings); 220 } 221 222 223 232 public final List getParameterListForSubmit( final SubmittableElement submitElement ) { 233 final Collection submittableElements = getAllSubmittableElements(submitElement); 234 235 final List parameterList = new ArrayList ( submittableElements.size() ); 236 final Iterator iterator = submittableElements.iterator(); 237 while( iterator.hasNext() ) { 238 final SubmittableElement element = ( SubmittableElement )iterator.next(); 239 final KeyValuePair[] pairs = element.getSubmitKeyValuePairs(); 240 241 for( int i = 0; i < pairs.length; i++ ) { 242 parameterList.add( pairs[i] ); 243 } 244 } 245 246 if( fakeSelectedRadioButton_ != null ) { 247 adjustParameterListToAccountForFakeSelectedRadioButton( parameterList ); 248 } 249 return parameterList; 250 } 251 252 253 259 public Page reset() { 260 final HtmlPage htmlPage = getPage(); 261 if( htmlPage.getWebClient().isJavaScriptEnabled() ) { 262 final String onReset = getOnResetAttribute(); 263 if( onReset.length() != 0 ) { 264 final ScriptResult scriptResult 265 = htmlPage.executeJavaScriptIfPossible( onReset, "onReset", true, this ); 266 if( scriptResult.getJavaScriptResult().equals(Boolean.FALSE) ) { 267 return scriptResult.getNewPage(); 268 } 269 } 270 } 271 272 final Iterator elementIterator = getAllHtmlChildElements(); 273 while( elementIterator.hasNext() ) { 274 final Object next = elementIterator.next(); 275 if( next instanceof SubmittableElement ) { 276 ((SubmittableElement)next).reset(); 277 } 278 } 279 280 return htmlPage; 281 } 282 283 292 public Collection getAllSubmittableElements(final SubmittableElement submitElement) { 293 return getSubmittableElements(submitElement); 294 } 295 296 304 public Collection getSubmittableElements(final SubmittableElement submitElement) { 305 306 final List submittableElements = new ArrayList (); 307 308 final DescendantElementsIterator iterator = getAllHtmlChildElements(); 309 while( iterator.hasNext() ) { 310 final HtmlElement element = ( HtmlElement )iterator.next(); 311 if( isSubmittable(element, submitElement) ) { 312 submittableElements.add(element); 313 } 314 } 315 316 return submittableElements; 317 } 318 319 private boolean isValidForSubmission(final HtmlElement element, final SubmittableElement submitElement){ 320 final String tagName = element.getTagName(); 321 if (!SUBMITTABLE_ELEMENT_NAMES.contains(tagName.toLowerCase())) { 322 return false; 323 } 324 if(element.isAttributeDefined("disabled")) { 325 return false; 326 } 327 if (element == submitElement && element instanceof HtmlImageInput) { 329 return true; 330 } 331 332 if (!tagName.equals("isindex") && !element.isAttributeDefined("name")){ 333 return false; 334 } 335 336 if( ! tagName.equals( "isindex" ) && element.getAttributeValue("name").equals("") ) { 337 return false; 338 } 339 340 if( tagName.equals( "input" ) ) { 341 final String type = element.getAttributeValue("type").toLowerCase(); 342 if( type.equals( "radio" ) || type.equals( "checkbox" ) ) { 343 return element.isAttributeDefined("checked"); 344 } 345 } 346 if ( tagName.equals("select") ) { 347 if (((HtmlSelect) element).getOptionSize() < 1) { 349 return false; 350 } 351 } 352 return true; 353 } 354 355 361 private boolean isSubmittable(final HtmlElement element, final SubmittableElement submitElement) { 362 final String tagName = element.getTagName(); 363 if (!isValidForSubmission(element, submitElement)){ 364 return false; 365 } 366 367 if (element == submitElement) { 369 return true; 370 } 371 if( tagName.equals( "input" ) ) { 372 final HtmlInput input = (HtmlInput)element; 373 final String type = input.getTypeAttribute().toLowerCase(); 374 if( type.equals("submit") || type.equals("image") ){ 375 return false; 376 } 377 } 378 if ( tagName.equals("button") ) { 379 final HtmlButton button = (HtmlButton)element; 380 final String type = button.getTypeAttribute().toLowerCase(); 381 if( type.equals("submit") ){ 382 return false; 383 } 384 } 385 386 return true; 387 } 388 389 397 public List getAllInputsByName( final String name ) { 398 return getInputsByName(name); 399 } 400 401 407 public List getInputsByName( final String name ) { 408 return getHtmlElementsByAttribute( "input", "name", name ); 409 } 410 411 418 public final HtmlInput getInputByName( final String name ) throws ElementNotFoundException { 419 final List inputs = getHtmlElementsByAttribute( "input", "name", name ); 420 if( inputs.size() == 0 ) { 421 throw new ElementNotFoundException( "input", "name", name ); 422 } 423 else { 424 return ( HtmlInput )inputs.get( 0 ); 425 } 426 } 427 428 429 437 public HtmlRadioButtonInput getRadioButtonInput( final String name, final String value ) 438 throws 439 ElementNotFoundException { 440 441 final DescendantElementsIterator iterator = getAllHtmlChildElements(); 442 while( iterator.hasNext() ) { 443 final HtmlElement element = iterator.nextElement(); 444 445 if( element instanceof HtmlRadioButtonInput 446 && element.getAttributeValue("name").equals( name ) ) { 447 448 final HtmlRadioButtonInput input = (HtmlRadioButtonInput)element; 449 if( input.getValueAttribute().equals( value ) ) { 450 return input; 451 } 452 } 453 } 454 throw new ElementNotFoundException( "input", "value", value ); 455 } 456 457 458 464 public List getSelectsByName( final String name ) { 465 return getHtmlElementsByAttribute( "select", "name", name ); 466 } 467 468 469 475 public HtmlSelect getSelectByName( final String name ) throws ElementNotFoundException { 476 final List list = getSelectsByName( name ); 477 if( list.isEmpty() ) { 478 throw new ElementNotFoundException( "select", "name", name ); 479 } 480 else { 481 return ( HtmlSelect )list.get( 0 ); 482 } 483 } 484 485 486 493 public List getButtonsByName( final String name ) 494 throws ElementNotFoundException { 495 return getHtmlElementsByAttribute( "button", "name", name ); 496 } 497 498 499 505 public List getTextAreasByName( final String name ) { 506 return getHtmlElementsByAttribute( "textarea", "name", name ); 507 } 508 509 510 517 public List getRadioButtonsByName( final String name ) { 518 519 Assert.notNull( "name", name ); 520 521 final List results = new ArrayList (); 522 523 final DescendantElementsIterator iterator = getAllHtmlChildElements(); 524 while( iterator.hasNext() ) { 525 final HtmlElement element = ( HtmlElement )iterator.next(); 526 if( element instanceof HtmlRadioButtonInput 527 && element.getAttributeValue("name").equals( name ) ) { 528 results.add(element); 529 } 530 } 531 532 return results; 533 } 534 535 536 548 public void setCheckedRadioButton( 549 final String name, 550 final String value ) 551 throws 552 ElementNotFoundException { 553 554 final HtmlInput inputToSelect = getRadioButtonInput( name, value ); 557 558 final DescendantElementsIterator iterator = getAllHtmlChildElements(); 559 while( iterator.hasNext() ) { 560 final HtmlElement element = iterator.nextElement(); 561 if( element instanceof HtmlRadioButtonInput 562 && element.getAttributeValue("name").equals( name ) ) { 563 564 final HtmlRadioButtonInput input = (HtmlRadioButtonInput)element; 565 if( input == inputToSelect ) { 566 input.setAttributeValue("checked", "checked"); 567 } 568 else { 569 input.removeAttribute("checked"); 570 } 571 } 572 } 573 } 574 575 584 public final void fakeCheckedRadioButton( 585 final String name, 586 final String value ) 587 throws 588 ElementNotFoundException { 589 590 fakeSelectedRadioButton_ = new KeyValuePair( name, value ); 591 } 592 593 594 private void adjustParameterListToAccountForFakeSelectedRadioButton( final List list ) { 595 final String fakeRadioButtonName = fakeSelectedRadioButton_.getKey(); 596 597 final Iterator iterator = list.iterator(); 599 while( iterator.hasNext() ) { 600 final KeyValuePair pair = ( KeyValuePair )iterator.next(); 601 if( pair.getKey().equals( fakeRadioButtonName ) ) { 602 iterator.remove(); 603 } 604 } 605 606 list.add( fakeSelectedRadioButton_ ); 608 } 609 610 611 618 public HtmlRadioButtonInput getCheckedRadioButton( final String name ) { 619 620 Assert.notNull("name", name); 621 622 final DescendantElementsIterator iterator = getAllHtmlChildElements(); 623 while( iterator.hasNext() ) { 624 final HtmlElement element = iterator.nextElement(); 625 if( element instanceof HtmlRadioButtonInput 626 && element.getAttributeValue("name").equals( name ) ) { 627 628 final HtmlRadioButtonInput input = (HtmlRadioButtonInput)element; 629 if( input.isChecked() ) { 630 return input; 631 } 632 } 633 } 634 return null; 635 } 636 637 638 646 public final String getActionAttribute() { 647 return getAttributeValue( "action" ); 648 } 649 650 651 658 public final void setActionAttribute( final String action ) { 659 setAttributeValue( "action", action ); 660 } 661 662 663 671 public final String getMethodAttribute() { 672 return getAttributeValue( "method" ); 673 } 674 675 676 684 public final void setMethodAttribute( final String method ) { 685 setAttributeValue( "method", method ); 686 } 687 688 689 697 public final String getNameAttribute() { 698 return getAttributeValue( "name" ); 699 } 700 701 702 712 public final String getEnctypeAttribute() { 713 return getAttributeValue( "enctype" ); 714 } 715 716 717 727 public final void setEnctypeAttribute( final String encoding ) { 728 setAttributeValue( "enctype", encoding ); 729 } 730 731 732 740 public final String getOnSubmitAttribute() { 741 return getAttributeValue( "onsubmit" ); 742 } 743 744 745 753 public final String getOnResetAttribute() { 754 return getAttributeValue( "onreset" ); 755 } 756 757 758 766 public final String getAcceptAttribute() { 767 return getAttributeValue( "accept" ); 768 } 769 770 771 779 public final String getAcceptCharsetAttribute() { 780 return getAttributeValue( "accept-charset" ); 781 } 782 783 784 792 public final String getTargetAttribute() { 793 return getAttributeValue( "target" ); 794 } 795 796 797 805 public final void setTargetAttribute( final String target ) { 806 setAttributeValue( "target", target ); 807 } 808 809 815 public HtmlInput getInputByValue( final String value ) throws ElementNotFoundException { 816 return (HtmlInput)getOneHtmlElementByAttribute("input", "value", value); 817 } 818 819 824 public List getInputsByValue( final String value ) { 825 return getHtmlElementsByAttribute("input", "value", value); 826 } 827 } 828 | Popular Tags |