From: <rb...@us...> - 2013-04-19 15:13:01
|
Revision: 8234 http://sourceforge.net/p/htmlunit/code/8234 Author: rbri Date: 2013-04-19 15:12:55 +0000 (Fri, 19 Apr 2013) Log Message: ----------- next try to behave like IE8 when working with radio buttons from JS Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlInput.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlRadioButtonInput.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Document.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Node.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLInputElement.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlRadioButtonInput2Test.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlInput.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlInput.java 2013-04-19 12:31:58 UTC (rev 8233) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlInput.java 2013-04-19 15:12:55 UTC (rev 8234) @@ -52,6 +52,7 @@ private String defaultValue_; private String originalName_; private Collection<String> previousNames_ = Collections.emptySet(); + private boolean createdByJavascript_ = false; /** * Creates an instance. @@ -523,4 +524,35 @@ public Collection<String> getPreviousNames() { return previousNames_; } + + /** + * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> + * + * Marks this frame as created by javascript. This is needed to handle + * some special IE behavior. + */ + public void markAsCreatedByJavascript() { + createdByJavascript_ = true; + } + + /** + * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> + * + * Unmarks this frame as created by javascript. This is needed to handle + * some special IE behavior. + */ + public void unmarkAsCreatedByJavascript() { + createdByJavascript_ = false; + } + + /** + * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> + * + * Returns true if this frame was created by javascript. This is needed to handle + * some special IE behavior. + * @return true or false + */ + public boolean wasCreatedByJavascript() { + return createdByJavascript_; + } } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlRadioButtonInput.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlRadioButtonInput.java 2013-04-19 12:31:58 UTC (rev 8233) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlRadioButtonInput.java 2013-04-19 15:12:55 UTC (rev 8234) @@ -17,6 +17,7 @@ import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.EVENT_ONCHANGE_LOSING_FOCUS; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.HTMLINPUT_DEFAULT_IS_CHECKED; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.HTMLRADIOINPUT_SET_CHECKED_TO_DEFAULT_WHEN_ADDED; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.HTMLRADIOINPUT_SET_CHECKED_TO_FALSE_WHEN_ADDED; import java.io.IOException; import java.util.Map; @@ -208,6 +209,9 @@ if (hasFeature(HTMLRADIOINPUT_SET_CHECKED_TO_DEFAULT_WHEN_ADDED)) { setChecked(isDefaultChecked()); } + if (wasCreatedByJavascript() && hasFeature(HTMLRADIOINPUT_SET_CHECKED_TO_FALSE_WHEN_ADDED)) { + removeAttribute("checked"); + } } /** Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Document.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Document.java 2013-04-19 12:31:58 UTC (rev 8233) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Document.java 2013-04-19 15:12:55 UTC (rev 8234) @@ -43,6 +43,7 @@ import com.gargoylesoftware.htmlunit.html.FrameWindow; import com.gargoylesoftware.htmlunit.html.HTMLParser; import com.gargoylesoftware.htmlunit.html.HtmlDivision; +import com.gargoylesoftware.htmlunit.html.HtmlInput; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.gargoylesoftware.htmlunit.html.impl.SimpleRange; import com.gargoylesoftware.htmlunit.javascript.SimpleScriptable; @@ -434,6 +435,9 @@ if (element instanceof BaseFrameElement) { ((BaseFrameElement) element).markAsCreatedByJavascript(); } + if (element instanceof HtmlInput) { + ((HtmlInput) element).markAsCreatedByJavascript(); + } final Object jsElement = getScriptableFor(element); if (jsElement == NOT_FOUND) { Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Node.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Node.java 2013-04-19 12:31:58 UTC (rev 8233) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Node.java 2013-04-19 15:12:55 UTC (rev 8234) @@ -18,7 +18,6 @@ import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.GENERATED_124; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.GENERATED_125; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.GENERATED_45; -import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.HTMLRADIOINPUT_SET_CHECKED_TO_FALSE_WHEN_ADDED; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_APPEND_CHILD_CREATE_DOCUMENT_FRAGMENT_PARENT; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_APPEND_CHILD_THROWS_NO_EXCEPTION_FOR_WRONG_NOTE; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_CLONE_NODE_COPIES_EVENT_LISTENERS; @@ -50,7 +49,6 @@ import com.gargoylesoftware.htmlunit.html.DomText; import com.gargoylesoftware.htmlunit.html.HtmlInlineFrame; import com.gargoylesoftware.htmlunit.html.HtmlPage; -import com.gargoylesoftware.htmlunit.html.HtmlRadioButtonInput; import com.gargoylesoftware.htmlunit.javascript.SimpleScriptable; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxClass; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxConstant; @@ -235,15 +233,6 @@ parentNode.appendChild(childDomNode); appendedChild = childObject; - // special hack for IE and radio buttons - // this can't be done in onAddedToPage() because - // it only happens when appendChild() is called. - if (childDomNode instanceof HtmlRadioButtonInput) { - final HtmlRadioButtonInput radio = (HtmlRadioButtonInput) childDomNode; - if (getBrowserVersion().hasFeature(HTMLRADIOINPUT_SET_CHECKED_TO_FALSE_WHEN_ADDED)) { - radio.setChecked(false); - } - } // if the parentNode has null parentNode in IE, // create a DocumentFragment to be the parentNode's parentNode. if (!(parentNode instanceof SgmlPage) @@ -434,16 +423,6 @@ appendedChild = newChildObject; } - // special hack for IE and radio buttons - // this can't be done in onAddedToPage() because - // it only happens when appendChild() is called. - if (newChildNode instanceof HtmlRadioButtonInput) { - final HtmlRadioButtonInput radio = (HtmlRadioButtonInput) newChildNode; - if (getBrowserVersion().hasFeature(HTMLRADIOINPUT_SET_CHECKED_TO_FALSE_WHEN_ADDED)) { - radio.setChecked(false); - } - } - // if parentNode is null in IE, create a DocumentFragment to be the parentNode if (domNode.getParentNode() == null && getBrowserVersion() .hasFeature(JS_APPEND_CHILD_CREATE_DOCUMENT_FRAGMENT_PARENT)) { Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLInputElement.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLInputElement.java 2013-04-19 12:31:58 UTC (rev 8233) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLInputElement.java 2013-04-19 15:12:55 UTC (rev 8234) @@ -69,6 +69,10 @@ final HtmlInput newInput = (HtmlInput) InputElementFactory.instance .createElement(input.getPage(), "input", attributes); + if (input.wasCreatedByJavascript()) { + newInput.markAsCreatedByJavascript(); + } + if (input.getParentNode() != null) { input.getParentNode().replaceChild(newInput, input); } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlRadioButtonInput2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlRadioButtonInput2Test.java 2013-04-19 12:31:58 UTC (rev 8233) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlRadioButtonInput2Test.java 2013-04-19 15:12:55 UTC (rev 8234) @@ -44,7 +44,7 @@ @Alerts(DEFAULT = { "true", "true", "true", "true", "true", "true" }, IE = { "true", "false", "false", "false", "false", "false" }, IE6 = { "true", "false", "false", "false", "true", "true" }) - public void checked_on_attachment() throws Exception { + public void checked_appendChild() throws Exception { final String html = "<html>\n" + "<head>\n" + " <script>\n" @@ -53,20 +53,22 @@ + " input.type = 'radio';\n" + " input.checked = true;\n" + " alert(input.checked);\n" - + " document.body.appendChild(input);\n" + + " var parent=document.getElementById('myDiv');\n" + + " parent.appendChild(input);\n" + " alert(input.checked);\n" - + " document.body.removeChild(input);\n" + + " parent.removeChild(input);\n" + " alert(input.checked);\n" + "\n" + " input.defaultChecked = true;\n" + " alert(input.checked);\n" - + " document.body.appendChild(input);\n" + + " parent.appendChild(input);\n" + " alert(input.checked);\n" - + " document.body.removeChild(input);\n" + + " parent.removeChild(input);\n" + " alert(input.checked);\n" + " }\n" + " </script>\n" + "</head><body onload='test()'>\n" + + " <form><div id='myDiv'></div></div></form>\n" + "</body></html>"; loadPageWithAlerts2(html); @@ -79,7 +81,7 @@ @Alerts(DEFAULT = { "false", "false", "false", "true", "true", "true" }, IE = { "false", "false", "false", "false", "false", "false" }, IE6 = { "false", "false", "false", "false", "true", "true" }) - public void notchecked_on_insertBefore() throws Exception { + public void notchecked_appendChild() throws Exception { final String html = "<html>\n" + "<head>\n" + " <script>\n" @@ -88,22 +90,21 @@ + " input.type = 'radio';\n" + " alert(input.checked);\n" + " var parent=document.getElementById('myDiv');\n" - + " var after=document.getElementById('divAfter');\n" - + " parent.insertBefore(input, after);\n" + + " parent.appendChild(input);\n" + " alert(input.checked);\n" + " parent.removeChild(input);\n" + " alert(input.checked);\n" + "\n" + " input.defaultChecked = true;\n" + " alert(input.checked);\n" - + " parent.insertBefore(input, after);\n" + + " parent.appendChild(input);\n" + " alert(input.checked);\n" + " parent.removeChild(input);\n" + " alert(input.checked);\n" + " }\n" + " </script>\n" + "</head><body onload='test()'>\n" - + " <div id='myDiv'><div id='divAfter'></div></div>\n" + + " <form><div id='myDiv'></div></form>\n" + "</body></html>"; loadPageWithAlerts2(html); @@ -113,17 +114,16 @@ * @throws Exception if the test fails */ @Test - @Alerts(DEFAULT = { "true", "true", "true", "true", "true", "true" }, - IE = { "true", "false", "false", "false", "false", "false" }, - IE6 = { "true", "false", "false", "false", "true", "true" }) - public void checked_on_insertBefore() throws Exception { + @Alerts(DEFAULT = { "false", "false", "false", "true", "true", "true" }, + IE = { "false", "false", "false", "false", "false", "false" }, + IE6 = { "false", "false", "false", "false", "true", "true" }) + public void notchecked_insertBefore() throws Exception { final String html = "<html>\n" + "<head>\n" + " <script>\n" + " function test() {\n" + " var input = document.createElement('input');\n" + " input.type = 'radio';\n" - + " input.checked = true;\n" + " alert(input.checked);\n" + " var parent=document.getElementById('myDiv');\n" + " var after=document.getElementById('divAfter');\n" @@ -141,7 +141,7 @@ + " }\n" + " </script>\n" + "</head><body onload='test()'>\n" - + " <div id='myDiv'><div id='divAfter'></div></div>\n" + + " <form><div id='myDiv'><div id='divAfter'></div></div></form>\n" + "</body></html>"; loadPageWithAlerts2(html); @@ -151,31 +151,35 @@ * @throws Exception if the test fails */ @Test - @Alerts(DEFAULT = { "false", "false", "false", "true", "true", "true" }, - IE = { "false", "false", "false", "false", "false", "false" }, - IE6 = { "false", "false", "false", "false", "true", "true" }) - public void notchecked_on_attachment() throws Exception { + @Alerts(DEFAULT = { "true", "true", "true", "true", "true", "true" }, + IE = { "true", "false", "false", "false", "false", "false" }, + IE6 = { "true", "false", "false", "false", "true", "true" }) + public void checked_insertBefore() throws Exception { final String html = "<html>\n" + "<head>\n" + " <script>\n" + " function test() {\n" + " var input = document.createElement('input');\n" + " input.type = 'radio';\n" + + " input.checked = true;\n" + " alert(input.checked);\n" - + " document.body.appendChild(input);\n" + + " var parent=document.getElementById('myDiv');\n" + + " var after=document.getElementById('divAfter');\n" + + " parent.insertBefore(input, after);\n" + " alert(input.checked);\n" - + " document.body.removeChild(input);\n" + + " parent.removeChild(input);\n" + " alert(input.checked);\n" + "\n" + " input.defaultChecked = true;\n" + " alert(input.checked);\n" - + " document.body.appendChild(input);\n" + + " parent.insertBefore(input, after);\n" + " alert(input.checked);\n" - + " document.body.removeChild(input);\n" + + " parent.removeChild(input);\n" + " alert(input.checked);\n" + " }\n" + " </script>\n" + "</head><body onload='test()'>\n" + + " <form><div id='myDiv'><div id='divAfter'></div></div></form>\n" + "</body></html>"; loadPageWithAlerts2(html); |