From: <asa...@us...> - 2012-12-31 13:36:35
|
Revision: 7929 http://sourceforge.net/p/htmlunit/code/7929 Author: asashour Date: 2012-12-31 13:36:31 +0000 (Mon, 31 Dec 2012) Log Message: ----------- CSS: support Selectors Level 3: - Remaining not() case will be resolved once the cssparser patch #6 is committed. Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheet.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSSelectorTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2012-12-31 08:07:59 UTC (rev 7928) +++ trunk/htmlunit/src/changes/changes.xml 2012-12-31 13:36:31 UTC (rev 7929) @@ -7,7 +7,10 @@ </properties> <body> - <release version="2.12" date="???" description="Bugfixes"> + <release version="2.12" date="???" description="Bugfixes, CSS3 Selectors"> + <action type="add" dev="asashour"> + CSS: support Selectors Level 3. + </action> <action type="update" dev="asashour"> JavaScript: fix document/element . querySelectorAll()/querySelector() (IE8). </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheet.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheet.java 2012-12-31 08:07:59 UTC (rev 7928) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheet.java 2012-12-31 13:36:31 UTC (rev 7929) @@ -36,6 +36,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import net.sourceforge.htmlunit.corejs.javascript.Context; @@ -45,6 +46,7 @@ import org.apache.commons.logging.LogFactory; import org.w3c.css.sac.AttributeCondition; import org.w3c.css.sac.CSSException; +import org.w3c.css.sac.CSSParseException; import org.w3c.css.sac.CombinatorCondition; import org.w3c.css.sac.Condition; import org.w3c.css.sac.ConditionalSelector; @@ -136,7 +138,7 @@ "focus", "lang", "first-child"); private static final Collection<String> CSS3_PSEUDO_CLASSES = new ArrayList<String>(Arrays.asList( - "checked", "disabled", "indeterminated", "root", "target", + "checked", "disabled", "indeterminated", "root", "target", "not()", "nth-child()", "nth-last-child()", "nth-of-type()", "nth-last-of-type()", "last-child", "first-of-type", "last-of-type", "only-child", "only-of-type", "empty")); @@ -665,6 +667,38 @@ else if ("empty".equals(value)) { return element.getFirstChild() == null; } + else if (value.startsWith("not(")) { + final String selectors = value.substring(value.indexOf('(') + 1, value.length() - 1); + final AtomicBoolean errorOccured = new AtomicBoolean(false); + final ErrorHandler errorHandler = new ErrorHandler() { + public void warning(final CSSParseException exception) throws CSSException { + // ignore + } + + public void fatalError(final CSSParseException exception) throws CSSException { + errorOccured.set(true); + } + + public void error(final CSSParseException exception) throws CSSException { + errorOccured.set(true); + } + }; + final CSSOMParser parser = new CSSOMParser(new SACParserCSS3()); + parser.setErrorHandler(errorHandler); + try { + final SelectorList selectorList = parser.parseSelectors(new InputSource(new StringReader(selectors))); + if (errorOccured.get() || selectorList == null || selectorList.getLength() != 1) { + throw new CSSException("Invalid selectors: " + selectors); + } + + validateSelectors(selectorList, 9); + + return !CSSStyleSheet.selects(browserVersion, selectorList.item(0), element); + } + catch (final IOException e) { + throw new CSSException("Error parsing CSS selectors from '" + selectors + "': " + e.getMessage()); + } + } return false; } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSSelectorTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSSelectorTest.java 2012-12-31 08:07:59 UTC (rev 7928) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSSelectorTest.java 2012-12-31 13:36:31 UTC (rev 7929) @@ -14,11 +14,14 @@ */ package com.gargoylesoftware.htmlunit.javascript.host.css; +import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.FF; + import org.junit.Test; import org.junit.runner.RunWith; import com.gargoylesoftware.htmlunit.BrowserRunner; import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts; +import com.gargoylesoftware.htmlunit.BrowserRunner.NotYetImplemented; import com.gargoylesoftware.htmlunit.WebDriverTestCase; import com.gargoylesoftware.htmlunit.html.HtmlPageTest; @@ -542,7 +545,7 @@ * @throws Exception if an error occurs */ @Test - @Alerts(DEFAULT = "id1", IE8 = "exception") + @Alerts(DEFAULT = "id2", IE8 = "exception") public void empty() throws Exception { final String html = "<html><head><title>First</title>\n" + "<meta http-equiv='X-UA-Compatible' content='IE=9'>\n" @@ -556,11 +559,37 @@ + "}\n" + "</script></head>\n" + "<body onload='test()'>\n" - + " <p id='id1'></p>\n" - + " <p id='id2'>Hello, World!</p>\n" + + " <p id='id1'>Hello, World!</p>\n" + + " <p id='id2'></p>\n" + "</body></html>"; loadPageWithAlerts2(html); } + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = "id2", IE8 = "exception") + @NotYetImplemented(FF) + public void not() throws Exception { + final String html = "<html><head><title>First</title>\n" + + "<meta http-equiv='X-UA-Compatible' content='IE=9'>\n" + + "<script>\n" + + "function test() {\n" + + " if (document.querySelectorAll) {\n" + + " try {\n" + + " alert(document.querySelectorAll('input:not([type=\"file\"])')[0].id);\n" + + " } catch(e) {alert('exception')}\n" + + " }\n" + + "}\n" + + "</script></head>\n" + + "<body onload='test()'>\n" + + " <input id='id1' type='file'>\n" + + " <input id='id2'>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + } |