about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/css/select.nim12
-rw-r--r--src/css/selparser.nim15
-rw-r--r--src/html/dom.nim11
3 files changed, 34 insertions, 4 deletions
diff --git a/src/css/select.nim b/src/css/select.nim
index e9f55b3c..015dbcc3 100644
--- a/src/css/select.nim
+++ b/src/css/select.nim
@@ -29,6 +29,7 @@ func pseudoSelectorMatches(elem: Element, sel: Selector): bool =
   of PSEUDO_ONLY_CHILD: return elem.parentNode.firstElementChild == elem and elem.parentNode.lastElementChild == elem
   of PSEUDO_HOVER: return elem.hover
   of PSEUDO_ROOT: return elem == elem.ownerDocument.root
+  of PSEUDO_NTH_CHILD: return int64(sel.pseudonum - 1) in elem.parentNode.children.low..elem.parentNode.children.high and elem.parentNode.children[int64(sel.pseudonum - 1)] == elem
 
 func selectorsMatch*(elem: Element, selectors: SelectorList): bool
 
@@ -113,9 +114,9 @@ func selectElems(document: Document, sel: Selector): seq[Element] =
   of TYPE_SELECTOR:
     return document.type_elements[sel.tag]
   of ID_SELECTOR:
-    return document.id_elements[sel.id]
+    return document.id_elements.getOrDefault(sel.id, newSeq[Element]())
   of CLASS_SELECTOR:
-    return document.class_elements[sel.class]
+    return document.class_elements.getOrDefault(sel.class, newSeq[Element]())
   of UNIVERSAL_SELECTOR:
     return document.all_elements
   of ATTR_SELECTOR:
@@ -139,7 +140,7 @@ func selectElems(document: Document, selectors: SelectorList): seq[Element] =
     result = result.filter((elem) => selectorMatches(elem, sellist[i]))
     inc i
 
-proc querySelector(document: Document, q: string): seq[Element] =
+proc querySelectorAll*(document: Document, q: string): seq[Element] =
   let ss = newStringStream(q)
   let cvals = parseListOfComponentValues(ss)
   let selectors = parseSelectors(cvals)
@@ -147,3 +148,8 @@ proc querySelector(document: Document, q: string): seq[Element] =
   for sel in selectors:
     result.add(document.selectElems(sel))
 
+proc querySelector*(document: Document, q: string): Element =
+  let elems = document.querySelectorAll(q)
+  if elems.len > 0:
+    return elems[0]
+  return nil
diff --git a/src/css/selparser.nim b/src/css/selparser.nim
index bd114876..dd38adad 100644
--- a/src/css/selparser.nim
+++ b/src/css/selparser.nim
@@ -19,7 +19,7 @@ type
 
   PseudoClass* = enum
     PSEUDO_FIRST_CHILD, PSEUDO_LAST_CHILD, PSEUDO_ONLY_CHILD, PSEUDO_HOVER,
-    PSEUDO_ROOT
+    PSEUDO_ROOT, PSEUDO_NTH_CHILD
 
   CombinatorType* = enum
     DESCENDANT_COMBINATOR, CHILD_COMBINATOR, NEXT_SIBLING_COMBINATOR,
@@ -47,6 +47,7 @@ type
       discard
     of PSEUDO_SELECTOR:
       pseudo*: PseudoClass
+      pseudonum*: float64
     of PSELEM_SELECTOR:
       elem*: PseudoElem
     of FUNC_SELECTOR:
@@ -291,6 +292,18 @@ proc parseSelectorFunction(state: var SelectorParser, cssfunction: CSSFunction)
     if state.query != QUERY_PSEUDO:
       return
     state.query = QUERY_TYPE
+  of "nth-child":
+    if state.query != QUERY_PSEUDO:
+      return
+    if cssfunction.value.len != 1 or not (cssfunction.value[0] of CSSToken):
+      return
+    if CSSToken(cssfunction.value[0]).tokenType != CSS_NUMBER_TOKEN:
+      return
+    let num = CSSToken(cssfunction.value[0]).nvalue
+    if num == float64(int64(num)):
+      state.addSelector(Selector(t: PSEUDO_SELECTOR, pseudo: PSEUDO_NTH_CHILD, pseudonum: num))
+    state.query = QUERY_TYPE
+    return
   else: return
   var fun = Selector(t: FUNC_SELECTOR, name: $cssfunction.name)
   state.addSelector(fun)
diff --git a/src/html/dom.nim b/src/html/dom.nim
index 3bbe07b7..924fa7a9 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -281,6 +281,17 @@ func attrb*(element: Element, s: string): bool =
     return true
   return false
 
+func textContent*(node: Node): string =
+  case node.nodeType
+  of DOCUMENT_NODE, DOCUMENT_TYPE_NODE:
+    return "" #TODO null
+  of CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE, TEXT_NODE:
+    return CharacterData(node).data
+  else:
+    for child in node.childNodes:
+      if child.nodeType != COMMENT_NODE:
+        result &= child.textContent
+
 func toInputType*(str: string): InputType =
   case str
   of "button": INPUT_BUTTON