From: <asa...@us...> - 2012-12-21 18:55:51
|
Revision: 7897 http://sourceforge.net/p/htmlunit/code/7897 Author: asashour Date: 2012-12-21 18:55:47 +0000 (Fri, 21 Dec 2012) Log Message: ----------- CSS3: support prefix/suffix/substring attributes and GeneralAdjacentSibling selectors Issue 1466 Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java 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/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java 2012-12-21 18:17:44 UTC (rev 7896) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleDeclaration.java 2012-12-21 18:55:47 UTC (rev 7897) @@ -69,7 +69,7 @@ import com.gargoylesoftware.htmlunit.javascript.host.html.HTMLHtmlElement; import com.steadystate.css.dom.CSSValueImpl; import com.steadystate.css.parser.CSSOMParser; -import com.steadystate.css.parser.SACParserCSS21; +import com.steadystate.css.parser.SACParserCSS3; /** * A JavaScript object for a CSSStyleDeclaration. @@ -5607,7 +5607,7 @@ final InputSource source = new InputSource(new StringReader(styleAttribute)); source.setURI(uri); final ErrorHandler errorHandler = getWindow().getWebWindow().getWebClient().getCssErrorHandler(); - final CSSOMParser parser = new CSSOMParser(new SACParserCSS21()); + final CSSOMParser parser = new CSSOMParser(new SACParserCSS3()); parser.setErrorHandler(errorHandler); try { styleDeclaration_ = parser.parseStyleDeclaration(source); 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-21 18:17:44 UTC (rev 7896) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSStyleSheet.java 2012-12-21 18:55:47 UTC (rev 7897) @@ -93,9 +93,13 @@ import com.steadystate.css.dom.CSSStyleRuleImpl; import com.steadystate.css.dom.CSSStyleSheetImpl; import com.steadystate.css.parser.CSSOMParser; -import com.steadystate.css.parser.SACParserCSS21; +import com.steadystate.css.parser.SACParserCSS3; import com.steadystate.css.parser.SelectorListImpl; +import com.steadystate.css.parser.selectors.GeneralAdjacentSelectorImpl; +import com.steadystate.css.parser.selectors.PrefixAttributeConditionImpl; import com.steadystate.css.parser.selectors.PseudoClassConditionImpl; +import com.steadystate.css.parser.selectors.SubstringAttributeConditionImpl; +import com.steadystate.css.parser.selectors.SuffixAttributeConditionImpl; /** * A JavaScript object for a Stylesheet. @@ -331,6 +335,17 @@ */ public static boolean selects(final BrowserVersion browserVersion, final Selector selector, final DomElement element) { + if (selector instanceof GeneralAdjacentSelectorImpl) { + final SiblingSelector ss = (SiblingSelector) selector; + for (DomNode prev = element.getPreviousSibling(); prev != null; prev = prev.getPreviousSibling()) { + if (prev instanceof HtmlElement + && selects(browserVersion, ss.getSelector(), (HtmlElement) prev) + && selects(browserVersion, ss.getSiblingSelector(), element)) { + return true; + } + } + return false; + } switch (selector.getSelectorType()) { case Selector.SAC_ANY_NODE_SELECTOR: return true; @@ -402,6 +417,18 @@ * @return <tt>true</tt> if it does apply, <tt>false</tt> if it doesn't apply */ static boolean selects(final BrowserVersion browserVersion, final Condition condition, final DomElement element) { + if (condition instanceof PrefixAttributeConditionImpl) { + final AttributeCondition ac = (AttributeCondition) condition; + return element.getAttribute(ac.getLocalName()).startsWith(ac.getValue()); + } + if (condition instanceof SuffixAttributeConditionImpl) { + final AttributeCondition ac = (AttributeCondition) condition; + return element.getAttribute(ac.getLocalName()).endsWith(ac.getValue()); + } + if (condition instanceof SubstringAttributeConditionImpl) { + final AttributeCondition ac = (AttributeCondition) condition; + return element.getAttribute(ac.getLocalName()).contains(ac.getValue()); + } switch (condition.getConditionType()) { case Condition.SAC_ID_CONDITION: final AttributeCondition ac4 = (AttributeCondition) condition; @@ -578,7 +605,7 @@ org.w3c.dom.css.CSSStyleSheet ss; try { final ErrorHandler errorHandler = getWindow().getWebWindow().getWebClient().getCssErrorHandler(); - final CSSOMParser parser = new CSSOMParser(new SACParserCSS21()); + final CSSOMParser parser = new CSSOMParser(new SACParserCSS3()); parser.setErrorHandler(errorHandler); ss = parser.parseStyleSheet(source, null, null); } @@ -605,7 +632,7 @@ SelectorList selectors; try { final ErrorHandler errorHandler = getWindow().getWebWindow().getWebClient().getCssErrorHandler(); - final CSSOMParser parser = new CSSOMParser(new SACParserCSS21()); + final CSSOMParser parser = new CSSOMParser(new SACParserCSS3()); parser.setErrorHandler(errorHandler); selectors = parser.parseSelectors(source); // in case of error parseSelectors returns null 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-21 18:17:44 UTC (rev 7896) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/css/CSSSelectorTest.java 2012-12-21 18:55:47 UTC (rev 7897) @@ -34,7 +34,7 @@ public class CSSSelectorTest extends WebDriverTestCase { /** - * Test for bug 1287: CSS3 selector is not yet supported. + * Test for bug 1287. * * @throws Exception if an error occurs */ @@ -163,4 +163,109 @@ loadPageWithAlerts2(html); } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts({ "1", "thing1" }) + public void prefixAttribute() throws Exception { + final String html + = HtmlPageTest.STANDARDS_MODE_PREFIX_ + "<html><head><title>First</title><script>\n" + + "function test() {\n" + + " try {\n" + + " var list = document.querySelectorAll('[id^=\"thing\"]');\n" + + " alert(list.length);\n" + + " alert(list[0].id);\n" + + " } catch(e) {alert('exception')}\n" + + "}\n" + + "</script></head>\n" + + "<body onload='test()'>\n" + + " <div></div>\n" + + " <ul id='something'></ul>\n" + + " <p></p>\n" + + " <ul id='thing1'></ul>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts({ "1", "something" }) + public void suffixAttribute() throws Exception { + final String html + = HtmlPageTest.STANDARDS_MODE_PREFIX_ + "<html><head><title>First</title><script>\n" + + "function test() {\n" + + " try {\n" + + " var list = document.querySelectorAll('[id$=\"thing\"]');\n" + + " alert(list.length);\n" + + " alert(list[0].id);\n" + + " } catch(e) {alert('exception')}\n" + + "}\n" + + "</script></head>\n" + + "<body onload='test()'>\n" + + " <div></div>\n" + + " <ul id='something'></ul>\n" + + " <p></p>\n" + + " <ul id='thing2'></ul>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts({ "2", "something", "thing2" }) + public void substringAttribute() throws Exception { + final String html + = HtmlPageTest.STANDARDS_MODE_PREFIX_ + "<html><head><title>First</title><script>\n" + + "function test() {\n" + + " try {\n" + + " var list = document.querySelectorAll('[id*=\"thing\"]');\n" + + " alert(list.length);\n" + + " alert(list[0].id);\n" + + " alert(list[1].id);\n" + + " } catch(e) {alert('exception')}\n" + + "}\n" + + "</script></head>\n" + + "<body onload='test()'>\n" + + " <div></div>\n" + + " <ul id='something'></ul>\n" + + " <p></p>\n" + + " <ul id='thing2'></ul>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts({ "1", "ul2" }) + public void generalAdjacentSelector() throws Exception { + final String html + = HtmlPageTest.STANDARDS_MODE_PREFIX_ + "<html><head><title>First</title><script>\n" + + "function test() {\n" + + " try {\n" + + " var list = document.querySelectorAll('div~ul');\n" + + " alert(list.length);\n" + + " alert(list[0].id);\n" + + " } catch(e) {alert('exception')}\n" + + "}\n" + + "</script></head>\n" + + "<body onload='test()'>\n" + + " <div></div>\n" + + " <p></p>\n" + + " <ul id='ul2'></ul>\n" + + "</body></html>"; + + loadPageWithAlerts2(html); + } + } |