diff options
author | bptato <nincsnevem662@gmail.com> | 2022-05-23 19:55:33 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2022-05-23 19:55:53 +0200 |
commit | c5e57f02c9fe8e35f9bbc09525e268c33f6a3f33 (patch) | |
tree | 3523e6ec87ecd996e45f0d564012f7a288e0f227 | |
parent | 7177a737f5feee60a9775560f2a953bae26bd96a (diff) | |
download | chawan-c5e57f02c9fe8e35f9bbc09525e268c33f6a3f33.tar.gz |
Add querySelector and querySelectorAll for Element
-rw-r--r-- | src/css/select.nim | 45 | ||||
-rw-r--r-- | src/html/dom.nim | 17 |
2 files changed, 62 insertions, 0 deletions
diff --git a/src/css/select.nim b/src/css/select.nim index 10f87113..1fa01ac5 100644 --- a/src/css/select.nim +++ b/src/css/select.nim @@ -140,6 +140,37 @@ func selectElems(document: Document, selectors: SelectorList): seq[Element] = result = result.filter((elem) => selectorMatches(elem, sellist[i])) inc i +func selectElems(element: Element, sel: Selector): seq[Element] = + case sel.t + of TYPE_SELECTOR: + return element.filterDescendants((elem) => elem.tagType == sel.tag) + of ID_SELECTOR: + return element.filterDescendants((elem) => elem.id == sel.id) + of CLASS_SELECTOR: + return element.filterDescendants((elem) => sel.class in elem.classList) + of UNIVERSAL_SELECTOR: + return element.all_descendants + of ATTR_SELECTOR: + return element.filterDescendants((elem) => attrSelectorMatches(elem, sel)) + of PSEUDO_SELECTOR: + return element.filterDescendants((elem) => pseudoSelectorMatches(elem, sel)) + of PSELEM_SELECTOR: + return element.all_descendants + of FUNC_SELECTOR: + return element.filterDescendants((elem) => selectorMatches(elem, sel)) + of COMBINATOR_SELECTOR: + return element.filterDescendants((elem) => selectorMatches(elem, sel)) + +func selectElems(element: Element, selectors: SelectorList): seq[Element] = + assert(selectors.len > 0) + let sellist = optimizeSelectorList(selectors) + result = element.selectElems(selectors[0]) + var i = 1 + + while i < sellist.len: + result = result.filter((elem) => selectorMatches(elem, sellist[i])) + inc i + proc querySelectorAll*(document: Document, q: string): seq[Element] = let ss = newStringStream(q) let cvals = parseListOfComponentValues(ss) @@ -153,3 +184,17 @@ proc querySelector*(document: Document, q: string): Element = if elems.len > 0: return elems[0] return nil + +proc querySelectorAll*(element: Element, q: string): seq[Element] = + let ss = newStringStream(q) + let cvals = parseListOfComponentValues(ss) + let selectors = parseSelectors(cvals) + + for sel in selectors: + result.add(element.selectElems(sel)) + +proc querySelector*(element: Element, q: string): Element = + let elems = element.querySelectorAll(q) + if elems.len > 0: + return elems[0] + return nil diff --git a/src/html/dom.nim b/src/html/dom.nim index d50c1c8e..aaa33163 100644 --- a/src/html/dom.nim +++ b/src/html/dom.nim @@ -199,6 +199,23 @@ iterator branch*(node: Node): Node {.inline.} = yield node node = node.parentElement +func filterDescendants*(element: Element, predicate: (proc(child: Element): bool)): seq[Element] = + var stack: seq[Element] + stack.add(element.children) + while stack.len > 0: + let child = stack.pop() + if predicate(child): + result.add(child) + stack.add(child.children) + +func all_descendants*(element: Element): seq[Element] = + var stack: seq[Element] + stack.add(element.children) + while stack.len > 0: + let child = stack.pop() + result.add(child) + stack.add(child.children) + # a == b or b in a's ancestors func contains*(a, b: Node): bool = for node in a.branch: |