use of com.gargoylesoftware.css.parser.selector.SelectorList in project htmlunit by HtmlUnit.
the class DomNode method getSelectorList.
/**
* Returns the {@link SelectorList}.
* @param selectors the selectors
* @param browserVersion the {@link BrowserVersion}
* @return the {@link SelectorList}
* @throws IOException if an error occurs
*/
protected SelectorList getSelectorList(final String selectors, final BrowserVersion browserVersion) throws IOException {
final CSSOMParser parser = new CSSOMParser(new CSS3Parser());
final CheckErrorHandler errorHandler = new CheckErrorHandler();
parser.setErrorHandler(errorHandler);
final SelectorList selectorList = parser.parseSelectors(selectors);
// in case of error parseSelectors returns null
if (errorHandler.errorDetected()) {
throw new CSSException("Invalid selectors: " + selectors);
}
if (selectorList != null) {
int documentMode = 9;
if (browserVersion.hasFeature(QUERYSELECTORALL_NOT_IN_QUIRKS)) {
final Object sobj = getPage().getScriptableObject();
if (sobj instanceof HTMLDocument) {
documentMode = ((HTMLDocument) sobj).getDocumentMode();
}
}
CSSStyleSheet.validateSelectors(selectorList, documentMode, this);
}
return selectorList;
}
use of com.gargoylesoftware.css.parser.selector.SelectorList in project htmlunit by HtmlUnit.
the class DomNode method closest.
/**
* @param selectorString the selector to test
* @return true if the element would be selected by the specified selector string; otherwise, returns false.
*/
public DomElement closest(final String selectorString) {
try {
final BrowserVersion browserVersion = getPage().getWebClient().getBrowserVersion();
final SelectorList selectorList = getSelectorList(selectorString, browserVersion);
DomNode current = this;
if (selectorList != null) {
do {
for (final Selector selector : selectorList) {
final DomElement elem = (DomElement) current;
if (CSSStyleSheet.selects(browserVersion, selector, elem, null, true)) {
return elem;
}
}
do {
current = current.getParentNode();
} while (current != null && !(current instanceof DomElement));
} while (current != null);
}
return null;
} catch (final IOException e) {
throw new CSSException("Error parsing CSS selectors from '" + selectorString + "': " + e.getMessage());
}
}
use of com.gargoylesoftware.css.parser.selector.SelectorList in project htmlunit by HtmlUnit.
the class CSSStyleSheet method selectsPseudoClass.
private static boolean selectsPseudoClass(final BrowserVersion browserVersion, final Condition condition, final DomElement element, final boolean fromQuerySelectorAll) {
if (browserVersion.hasFeature(QUERYSELECTORALL_NOT_IN_QUIRKS)) {
final Object sobj = element.getPage().getScriptableObject();
if (sobj instanceof HTMLDocument && ((HTMLDocument) sobj).getDocumentMode() < 8) {
return false;
}
}
final String value = condition.getValue();
switch(value) {
case "root":
return element == element.getPage().getDocumentElement();
case "enabled":
return element instanceof DisabledElement && !((DisabledElement) element).isDisabled();
case "disabled":
return element instanceof DisabledElement && ((DisabledElement) element).isDisabled();
case "focus":
final HtmlPage htmlPage = element.getHtmlPageOrNull();
if (htmlPage != null) {
final DomElement focus = htmlPage.getFocusedElement();
return element == focus;
}
return false;
case "checked":
return (element instanceof HtmlCheckBoxInput && ((HtmlCheckBoxInput) element).isChecked()) || (element instanceof HtmlRadioButtonInput && ((HtmlRadioButtonInput) element).isChecked() || (element instanceof HtmlOption && ((HtmlOption) element).isSelected()));
case "required":
return element instanceof HtmlElement && ((HtmlElement) element).isRequired();
case "optional":
return element instanceof HtmlElement && ((HtmlElement) element).isOptional();
case "first-child":
for (DomNode n = element.getPreviousSibling(); n != null; n = n.getPreviousSibling()) {
if (n instanceof DomElement) {
return false;
}
}
return true;
case "last-child":
for (DomNode n = element.getNextSibling(); n != null; n = n.getNextSibling()) {
if (n instanceof DomElement) {
return false;
}
}
return true;
case "first-of-type":
final String firstType = element.getNodeName();
for (DomNode n = element.getPreviousSibling(); n != null; n = n.getPreviousSibling()) {
if (n instanceof DomElement && n.getNodeName().equals(firstType)) {
return false;
}
}
return true;
case "last-of-type":
final String lastType = element.getNodeName();
for (DomNode n = element.getNextSibling(); n != null; n = n.getNextSibling()) {
if (n instanceof DomElement && n.getNodeName().equals(lastType)) {
return false;
}
}
return true;
case "only-child":
for (DomNode n = element.getPreviousSibling(); n != null; n = n.getPreviousSibling()) {
if (n instanceof DomElement) {
return false;
}
}
for (DomNode n = element.getNextSibling(); n != null; n = n.getNextSibling()) {
if (n instanceof DomElement) {
return false;
}
}
return true;
case "only-of-type":
final String type = element.getNodeName();
for (DomNode n = element.getPreviousSibling(); n != null; n = n.getPreviousSibling()) {
if (n instanceof DomElement && n.getNodeName().equals(type)) {
return false;
}
}
for (DomNode n = element.getNextSibling(); n != null; n = n.getNextSibling()) {
if (n instanceof DomElement && n.getNodeName().equals(type)) {
return false;
}
}
return true;
case "valid":
return element instanceof HtmlElement && ((HtmlElement) element).isValid();
case "invalid":
return element instanceof HtmlElement && !((HtmlElement) element).isValid();
case "empty":
return isEmpty(element);
case "target":
final String ref = element.getPage().getUrl().getRef();
return StringUtils.isNotBlank(ref) && ref.equals(element.getId());
case "hover":
return element.isMouseOver();
case "placeholder-shown":
if (browserVersion.hasFeature(CSS_PSEUDO_SELECTOR_PLACEHOLDER_SHOWN)) {
return element instanceof HtmlInput && StringUtils.isEmpty(((HtmlInput) element).getValueAttribute()) && StringUtils.isNotEmpty(((HtmlInput) element).getPlaceholder());
}
case "-ms-input-placeholder":
if (browserVersion.hasFeature(CSS_PSEUDO_SELECTOR_MS_PLACEHHOLDER)) {
return element instanceof HtmlInput && StringUtils.isEmpty(((HtmlInput) element).getValueAttribute()) && StringUtils.isNotEmpty(((HtmlInput) element).getPlaceholder());
}
default:
if (value.startsWith("nth-child(")) {
final String nth = value.substring(value.indexOf('(') + 1, value.length() - 1);
int index = 0;
for (DomNode n = element; n != null; n = n.getPreviousSibling()) {
if (n instanceof DomElement) {
index++;
}
}
return getNth(nth, index);
} else if (value.startsWith("nth-last-child(")) {
final String nth = value.substring(value.indexOf('(') + 1, value.length() - 1);
int index = 0;
for (DomNode n = element; n != null; n = n.getNextSibling()) {
if (n instanceof DomElement) {
index++;
}
}
return getNth(nth, index);
} else if (value.startsWith("nth-of-type(")) {
final String nthType = element.getNodeName();
final String nth = value.substring(value.indexOf('(') + 1, value.length() - 1);
int index = 0;
for (DomNode n = element; n != null; n = n.getPreviousSibling()) {
if (n instanceof DomElement && n.getNodeName().equals(nthType)) {
index++;
}
}
return getNth(nth, index);
} else if (value.startsWith("nth-last-of-type(")) {
final String nthLastType = element.getNodeName();
final String nth = value.substring(value.indexOf('(') + 1, value.length() - 1);
int index = 0;
for (DomNode n = element; n != null; n = n.getNextSibling()) {
if (n instanceof DomElement && n.getNodeName().equals(nthLastType)) {
index++;
}
}
return getNth(nth, index);
} else if (value.startsWith("not(")) {
final String selectors = value.substring(value.indexOf('(') + 1, value.length() - 1);
final AtomicBoolean errorOccured = new AtomicBoolean(false);
final CSSErrorHandler errorHandler = new CSSErrorHandler() {
@Override
public void warning(final CSSParseException exception) throws CSSException {
// ignore
}
@Override
public void fatalError(final CSSParseException exception) throws CSSException {
errorOccured.set(true);
}
@Override
public void error(final CSSParseException exception) throws CSSException {
errorOccured.set(true);
}
};
final CSSOMParser parser = new CSSOMParser(new CSS3Parser());
parser.setErrorHandler(errorHandler);
try {
final SelectorList selectorList = parser.parseSelectors(selectors);
if (errorOccured.get() || selectorList == null || selectorList.size() != 1) {
throw new CSSException("Invalid selectors: " + selectors);
}
validateSelectors(selectorList, 9, element);
return !selects(browserVersion, selectorList.get(0), element, null, fromQuerySelectorAll);
} catch (final IOException e) {
throw new CSSException("Error parsing CSS selectors from '" + selectors + "': " + e.getMessage());
}
}
return false;
}
}
use of com.gargoylesoftware.css.parser.selector.SelectorList in project htmlunit by HtmlUnit.
the class CSSStyleSheet method index.
private void index(final CSSStyleSheetImpl.CSSStyleSheetRuleIndex index, final CSSRuleListImpl ruleList, final Set<String> alreadyProcessing) {
for (final AbstractCSSRuleImpl rule : ruleList.getRules()) {
if (rule instanceof CSSStyleRuleImpl) {
final CSSStyleRuleImpl styleRule = (CSSStyleRuleImpl) rule;
final SelectorList selectors = styleRule.getSelectors();
for (final Selector selector : selectors) {
final SimpleSelector simpleSel = selector.getSimpleSelector();
if (SelectorType.ELEMENT_NODE_SELECTOR == simpleSel.getSelectorType()) {
final ElementSelector es = (ElementSelector) simpleSel;
boolean wasClass = false;
final List<Condition> conds = es.getConditions();
if (conds != null && conds.size() == 1) {
final Condition c = conds.get(0);
if (ConditionType.CLASS_CONDITION == c.getConditionType()) {
index.addClassSelector(es, c.getValue(), selector, styleRule);
wasClass = true;
}
}
if (!wasClass) {
index.addElementSelector(es, selector, styleRule);
}
} else {
index.addOtherSelector(selector, styleRule);
}
}
} else if (rule instanceof CSSImportRuleImpl) {
final CSSImportRuleImpl importRule = (CSSImportRuleImpl) rule;
final CSSStyleSheet sheet = getImportedStyleSheet(importRule);
if (!alreadyProcessing.contains(sheet.getUri())) {
final CSSRuleListImpl sheetRuleList = sheet.getWrappedSheet().getCssRules();
alreadyProcessing.add(sheet.getUri());
final MediaListImpl mediaList = importRule.getMedia();
if (mediaList.getLength() == 0 && index.getMediaList().getLength() == 0) {
index(index, sheetRuleList, alreadyProcessing);
} else {
index(index.addMedia(mediaList), sheetRuleList, alreadyProcessing);
}
}
} else if (rule instanceof CSSMediaRuleImpl) {
final CSSMediaRuleImpl mediaRule = (CSSMediaRuleImpl) rule;
final MediaListImpl mediaList = mediaRule.getMediaList();
if (mediaList.getLength() == 0 && index.getMediaList().getLength() == 0) {
index(index, mediaRule.getCssRules(), alreadyProcessing);
} else {
index(index.addMedia(mediaList), mediaRule.getCssRules(), alreadyProcessing);
}
}
}
}
use of com.gargoylesoftware.css.parser.selector.SelectorList in project LoboEvolution by LoboEvolution.
the class ElementImpl method querySelector.
/**
* {@inheritDoc}
*/
@Override
public Element querySelector(String selectors) {
SelectorList selectorList = CSSUtilities.getSelectorList(selectors);
List<Element> elem = new ArrayList<>();
if (selectorList != null) {
NodeListImpl childNodes = (NodeListImpl) getDescendents(new ElementFilter(null), true);
childNodes.forEach(child -> {
for (Selector selector : selectorList) {
if (child instanceof Element && StyleSheetAggregator.selects(selector, child, null)) {
elem.add((Element) child);
}
}
});
}
return elem.size() > 0 ? elem.get(0) : null;
}
Aggregations