private JsNodeArray getElementsByPseudo( JsNodeArray previousMatch, String pseudoClass, String pseudoValue) { JsNodeArray prevParents = JsNodeArray.create(); boolean previousDir = pseudoClass.startsWith("first") ? true : false; JsNodeArray matchingElms = JsNodeArray.create(); if (JsUtils.eq("first-child", pseudoClass) || JsUtils.eq("last-child", pseudoClass)) { getFirstChildPseudo(previousMatch, previousDir, matchingElms); } else if (JsUtils.eq("only-child", pseudoClass)) { getOnlyChildPseudo(previousMatch, matchingElms); } else if (JsUtils.eq("nth-child", pseudoClass)) { matchingElms = getNthChildPseudo(previousMatch, pseudoValue, prevParents, matchingElms); } else if (JsUtils.eq("first-of-type", pseudoClass) || JsUtils.eq("last-of-type", pseudoClass)) { getFirstOfTypePseudo(previousMatch, previousDir, matchingElms); } else if (JsUtils.eq("only-of-type", pseudoClass)) { getOnlyOfTypePseudo(previousMatch, matchingElms); } else if (JsUtils.eq("nth-of-type", pseudoClass)) { matchingElms = getNthOfTypePseudo(previousMatch, pseudoValue, prevParents, matchingElms); } else if (JsUtils.eq("empty", pseudoClass)) { getEmptyPseudo(previousMatch, matchingElms); } else if (JsUtils.eq("enabled", pseudoClass)) { getEnabledPseudo(previousMatch, matchingElms); } else if (JsUtils.eq("disabled", pseudoClass)) { getDisabledPseudo(previousMatch, matchingElms); } else if (JsUtils.eq("checked", pseudoClass)) { getCheckedPseudo(previousMatch, matchingElms); } else if (JsUtils.eq("contains", pseudoClass)) { getContainsPseudo(previousMatch, pseudoValue, matchingElms); } else if (JsUtils.eq("not", pseudoClass)) { matchingElms = getNotPseudo(previousMatch, pseudoValue, matchingElms); } else { getDefaultPseudo(previousMatch, pseudoClass, pseudoValue, matchingElms); } return matchingElms; }
public NodeList<Element> select(String sel, Node ctx) { String selectors[] = sel.replace("\\s*(,)\\s*", "$1").split(","); boolean identical = false; JsNodeArray elm = JsNodeArray.create(); for (int a = 0, len = selectors.length; a < len; a++) { if (a > 0) { identical = false; for (int b = 0, bl = a; b < bl; b++) { if (JsUtils.eq(selectors[a], selectors[b])) { identical = true; break; } } if (identical) { continue; } } String currentRule = selectors[a]; JsObjectArray<String> cssSelectors = selectorSplitRegExp.match(currentRule); JsNodeArray prevElem = JsNodeArray.create(ctx); for (int i = 0, slen = cssSelectors.length(); i < slen; i++) { JsNodeArray matchingElms = JsNodeArray.create(); String rule = cssSelectors.get(i); if (i > 0 && childOrSiblingRefRegExp.test(rule)) { JsObjectArray<String> childOrSiblingRef = childOrSiblingRefRegExp.exec(rule); if (JsUtils.truth(childOrSiblingRef)) { JsObjectArray<String> nextTag = new JsRegexp("^\\w+").exec(cssSelectors.get(i + 1)); JsRegexp nextRegExp = null; String nextTagStr = null; if (JsUtils.truth(nextTag)) { nextTagStr = nextTag.get(0); nextRegExp = new JsRegexp("(^|\\s)" + nextTagStr + "(\\s|$)", "i"); } for (int j = 0, jlen = prevElem.size(); j < jlen; j++) { Node prevRef = prevElem.getNode(j); String ref = childOrSiblingRef.get(0); if (JsUtils.eq(">", ref)) { getDescendantNodes(matchingElms, nextTagStr, prevRef); } else if (JsUtils.eq("+", ref)) { getSiblingNodes(matchingElms, nextTag, nextRegExp, prevRef); } else if (JsUtils.eq("~", ref)) { getGeneralSiblingNodes(matchingElms, nextTag, nextRegExp, prevRef); } } prevElem = matchingElms; clearAdded(prevElem); rule = cssSelectors.get(++i); if (new JsRegexp("^\\w+$").test(rule)) { continue; } setSkipTag(prevElem, true); } } JsObjectArray<String> cssSelector = cssSelectorRegExp.exec(rule); SplitRule splitRule = new SplitRule( !JsUtils.truth(cssSelector.get(1)) || JsUtils.eq(cssSelector.get(3), "*") ? "*" : cssSelector.get(1), !JsUtils.eq(cssSelector.get(3), "*") ? cssSelector.get(2) : null, cssSelector.get(4), cssSelector.get(6), cssSelector.get(10)); if (JsUtils.truth(splitRule.id)) { Element domelem = Document.get().getElementById(splitRule.id.substring(1)); if (JsUtils.truth(domelem)) { matchingElms = JsNodeArray.create(domelem); } prevElem = matchingElms; } else if (JsUtils.truth(splitRule.tag) && !isSkipped(prevElem)) { if (i == 0 && matchingElms.size() == 0 && prevElem.size() == 1) { prevElem = matchingElms = JsNodeArray.create(getElementsByTagName(splitRule.tag, prevElem.getNode(0))); } else { NodeList<Element> tagCollectionMatches; for (int l = 0, ll = prevElem.size(); l < ll; l++) { tagCollectionMatches = getElementsByTagName(splitRule.tag, prevElem.getNode(l)); for (int m = 0, mlen = tagCollectionMatches.getLength(); m < mlen; m++) { Node tagMatch = tagCollectionMatches.getItem(m); if (!isAdded(tagMatch)) { setAdded(tagMatch, true); matchingElms.addNode(tagMatch); } } } prevElem = matchingElms; clearAdded(prevElem); } if (matchingElms.size() == 0) { break; } setSkipTag(prevElem, false); if (JsUtils.truth(splitRule.allClasses)) { String[] allClasses = splitRule.allClasses.replaceFirst("^\\.", "").split("\\."); JsRegexp[] regExpClassNames = new JsRegexp[allClasses.length]; for (int n = 0, nl = allClasses.length; n < nl; n++) { regExpClassNames[n] = new JsRegexp("(^|\\s)" + allClasses[n] + "(\\s|$)"); } JsNodeArray matchingClassElms = JsNodeArray.create(); for (int o = 0, olen = prevElem.size(); o < olen; o++) { Element current = prevElem.getElement(o); String elmClass = current.getClassName(); boolean addElm = false; if (JsUtils.truth(elmClass) && !isAdded(current)) { for (int p = 0, pl = regExpClassNames.length; p < pl; p++) { addElm = regExpClassNames[p].test(elmClass); if (!addElm) { break; } } if (addElm) { setAdded(current, true); matchingClassElms.addNode(current); } } } clearAdded(prevElem); prevElem = matchingElms = matchingClassElms; } if (JsUtils.truth(splitRule.allAttr)) { JsObjectArray<String> allAttr = JsRegexp.match("\\[[^\\]]+\\]", "g", splitRule.allAttr); JsRegexp[] regExpAttributes = new JsRegexp[allAttr.length()]; String[] regExpAttributesStr = new String[allAttr.length()]; JsRegexp attributeMatchRegExp = new JsRegexp("(\\w+)(\\^|\\$|\\*|\\||~)?=?[\"']?([\\w\u00C0-\uFFFF\\s\\-_\\.]+)?"); for (int q = 0, ql = allAttr.length(); q < ql; q++) { JsObjectArray<String> attributeMatch = attributeMatchRegExp.exec(allAttr.get(q)); String attributeValue = JsUtils.truth(attributeMatch.get(3)) ? attributeMatch.get(3).replaceAll("\\.", "\\.") : null; String attrVal = attrToRegExp(attributeValue, (JsUtils.or(attributeMatch.get(2), null))); regExpAttributes[q] = (JsUtils.truth(attrVal) ? new JsRegexp(attrVal) : null); regExpAttributesStr[q] = attributeMatch.get(1); } JsNodeArray matchingAttributeElms = JsNodeArray.create(); for (int r = 0, rlen = matchingElms.size(); r < rlen; r++) { Element current = matchingElms.getElement(r); boolean addElm = false; for (int s = 0, sl = regExpAttributes.length; s < sl; s++) { addElm = false; JsRegexp attributeRegexp = regExpAttributes[s]; String currentAttr = getAttr(current, regExpAttributesStr[s]); if (JsUtils.truth(currentAttr) && currentAttr.length() != 0) { if (attributeRegexp == null || attributeRegexp.test(currentAttr)) { addElm = true; } } if (!addElm) { break; } } if (addElm) { matchingAttributeElms.addNode(current); } } prevElem = matchingElms = matchingAttributeElms; } if (JsUtils.truth(splitRule.allPseudos)) { JsRegexp pseudoSplitRegExp = new JsRegexp(":(\\w[\\w\\-]*)(\\(([^\\)]+)\\))?"); JsObjectArray<String> allPseudos = JsRegexp.match("(:\\w+[\\w\\-]*)(\\([^\\)]+\\))?", "g", splitRule.allPseudos); for (int t = 0, tl = allPseudos.length(); t < tl; t++) { JsObjectArray<String> pseudo = pseudoSplitRegExp.match(allPseudos.get(t)); String pseudoClass = JsUtils.truth(pseudo.get(1)) ? pseudo.get(1).toLowerCase() : null; String pseudoValue = JsUtils.truth(pseudo.get(3)) ? pseudo.get(3) : null; matchingElms = getElementsByPseudo(matchingElms, pseudoClass, pseudoValue); clearAdded(matchingElms); } prevElem = matchingElms; } } } elm.pushAll(prevElem); } return JsUtils.unique(elm.<JsArray<Element>>cast()).cast(); }