From: <rb...@us...> - 2013-07-21 12:34:48
|
Revision: 8416 http://sourceforge.net/p/htmlunit/code/8416 Author: rbri Date: 2013-07-21 12:34:44 +0000 (Sun, 21 Jul 2013) Log Message: ----------- Method document.createStyleSheet is more compatible with the IE; now the associated link node is also created and inserted at the right place in the header. The new link node is the ownerNode of the stylesheet. Issue 1520 Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/StyleSheetList.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocument.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Document2Test.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2013-07-21 09:30:10 UTC (rev 8415) +++ trunk/htmlunit/src/changes/changes.xml 2013-07-21 12:34:44 UTC (rev 8416) @@ -8,6 +8,11 @@ <body> <release version="2.13" date="???" description="Bugfixes"> + <action type="fix" dev="rbri" issue="1520"> + Method document.createStyleSheet is more compatible with the IE; now the associated + link node is also created and inserted at the right place in the header. The new link + node is the ownerNode of the stylesheet. + </action> <action type="fix" dev="rbri"> Using a wrong index when addressing an StyleSheetList always throws an Exception in IE. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/StyleSheetList.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/StyleSheetList.java 2013-07-21 09:30:10 UTC (rev 8415) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/StyleSheetList.java 2013-07-21 12:34:44 UTC (rev 8416) @@ -58,6 +58,19 @@ private HTMLCollection nodes_; /** + * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br/> + * + * Verifies if the provided node is a link node pointing to a stylesheet. + * + * @param domNode the mode to check + * @return true if the provided node is a stylesheet link + */ + public static boolean isStyleSheetLink(final DomNode domNode) { + return domNode instanceof HtmlLink + && "stylesheet".equalsIgnoreCase(((HtmlLink) domNode).getRelAttribute()); + } + + /** * Rhino requires default constructors. */ public StyleSheetList() { @@ -79,8 +92,7 @@ @Override protected boolean isMatching(final DomNode node) { return node instanceof HtmlStyle - || (node instanceof HtmlLink - && "stylesheet".equalsIgnoreCase(((HtmlLink) node).getRelAttribute())); + || isStyleSheetLink(node); } @Override Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocument.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocument.java 2013-07-21 09:30:10 UTC (rev 8415) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/html/HTMLDocument.java 2013-07-21 12:34:44 UTC (rev 8416) @@ -46,6 +46,7 @@ import static com.gargoylesoftware.htmlunit.util.StringUtils.parseHttpDate; import java.io.IOException; +import java.io.StringReader; import java.net.MalformedURLException; import java.net.URL; import java.text.SimpleDateFormat; @@ -69,12 +70,14 @@ import net.sourceforge.htmlunit.corejs.javascript.FunctionObject; import net.sourceforge.htmlunit.corejs.javascript.Scriptable; import net.sourceforge.htmlunit.corejs.javascript.ScriptableObject; +import net.sourceforge.htmlunit.corejs.javascript.Undefined; import net.sourceforge.htmlunit.corejs.javascript.UniqueTag; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.css.sac.CSSException; +import org.w3c.css.sac.InputSource; import org.w3c.dom.DOMException; import org.w3c.dom.DocumentType; @@ -97,6 +100,7 @@ import com.gargoylesoftware.htmlunit.html.HtmlAttributeChangeEvent; import com.gargoylesoftware.htmlunit.html.HtmlElement; import com.gargoylesoftware.htmlunit.html.HtmlForm; +import com.gargoylesoftware.htmlunit.html.HtmlHead; import com.gargoylesoftware.htmlunit.html.HtmlImage; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.gargoylesoftware.htmlunit.html.HtmlScript; @@ -1222,11 +1226,41 @@ * @return the newly created stylesheet */ @JsxFunction(@WebBrowser(IE)) - public CSSStyleSheet createStyleSheet(final String url, final int index) { - // minimal implementation - final CSSStyleSheet stylesheet = new CSSStyleSheet(); + public CSSStyleSheet createStyleSheet(final String url, final Object index) { + final HTMLLinkElement link = (HTMLLinkElement) createElement("link"); + link.setHref(url); + link.setRel("stylesheet"); + + int insertPos = Integer.MAX_VALUE; + if (Undefined.instance != index) { + try { + insertPos = ((Double) index).intValue(); + } + catch (final NumberFormatException e) { + // ignore + } + } + final InputSource source = new InputSource(new StringReader("")); + final CSSStyleSheet stylesheet = new CSSStyleSheet(link, source, url); stylesheet.setPrototype(getPrototype(CSSStyleSheet.class)); stylesheet.setParentScope(getWindow()); + + final HTMLCollection heads = getElementsByTagName("head"); + if (heads.getLength() > 0) { + final HtmlHead head = (HtmlHead) heads.item(0); + + int stylesheetPos = -1; + for (DomNode domNode : head.getChildNodes()) { + if (StyleSheetList.isStyleSheetLink(domNode)) { + stylesheetPos++; + if (insertPos <= stylesheetPos) { + domNode.insertBefore(link.getDomNodeOrDie()); + return stylesheet; + } + } + } + head.appendChild(link.getDomNodeOrDie()); + } return stylesheet; } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Document2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Document2Test.java 2013-07-21 09:30:10 UTC (rev 8415) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/Document2Test.java 2013-07-21 12:34:44 UTC (rev 8416) @@ -465,4 +465,89 @@ loadPageWithAlerts2(html); } + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(IE = { "style.css", "LINK" }, + DEFAULT = { }) + public void createStyleSheet() throws Exception { + final String html + = "<html><head><title>First</title>\n" + + "<script>\n" + + " function doTest() {\n" + + " if (document.createStyleSheet) {\n" + + " document.createStyleSheet('style.css');\n" + + " for (var si = 0; si < document.styleSheets.length; si++) {\n" + + " var sheet = document.styleSheets[si];\n" + + " alert(sheet.href);\n" + + " alert(sheet.owningElement.tagName);\n" + + " }\n" + + " }\n" + + " }\n" + + "</script></head>\n" + + "<body onload='doTest()'>\n" + + " <div id='id1'></div>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(IE = { "null", "" }, + DEFAULT = { }) + public void createStyleSheet_emptyUrl() throws Exception { + final String html + = "<html><head><title>First</title>\n" + + "<script>\n" + + " function doTest() {\n" + + " if (document.createStyleSheet) {\n" + + " document.createStyleSheet(null);\n" + + " document.createStyleSheet('');\n" + + " for (var si = 0; si < document.styleSheets.length; si++) {\n" + + " var sheet = document.styleSheets[si];\n" + + " alert(sheet.href);\n" + + " }\n" + + " }\n" + + " }\n" + + "</script></head>\n" + + "<body onload='doTest()'>\n" + + " <div id='id1'></div>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(IE = { "zero.css", "minus1.css", "seven.css", "none.css" }, + DEFAULT = { }) + public void createStyleSheet_insertAt() throws Exception { + final String html + = "<html><head><title>First</title>\n" + + "<script>\n" + + " function doTest() {\n" + + " if (document.createStyleSheet) {\n" + + " document.createStyleSheet('minus1.css', -1);\n" + + " document.createStyleSheet('zero.css', 0);\n" + + " document.createStyleSheet('seven.css', 7);\n" + + " document.createStyleSheet('none.css');\n" + + " for (var si = 0; si < document.styleSheets.length; si++) {\n" + + " var sheet = document.styleSheets[si];\n" + + " alert(sheet.href);\n" + + " }\n" + + " }\n" + + " }\n" + + "</script></head>\n" + + "<body onload='doTest()'>\n" + + " <div id='id1'></div>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } } |