@@ -2,6 +2,7 @@ package GoHtml
22
33import (
44 "strings"
5+
56 "golang.org/x/net/html"
67)
78
@@ -38,7 +39,7 @@ func (node *Node) SetPreviousNode(previousNode *Node) {
3839 node .previousNode = previousNode
3940}
4041
41- // GetChildNode returns the first child elements of this node.
42+ // GetChildNode returns the first child node of this node.
4243func (node * Node ) GetChildNode () * Node {
4344 return node .childNode
4445}
@@ -75,7 +76,7 @@ func (node *Node) GetAttribute(attributeName string) (string, bool) {
7576// RemoveAttribute remove or delete the specified attribute.
7677func (node * Node ) RemoveAttribute (attributeName string ) {
7778 delete (node .attributes , strings .TrimSpace (strings .ToLower (attributeName )))
78-
79+
7980}
8081
8182// IterateAttributes calls callback at every attribute in the node by passing attribute and value of the node.
@@ -114,19 +115,21 @@ func (node *Node) AppendChild(childNode *Node) {
114115
115116 lastNode := node .GetChildNode ().GetLastNode ()
116117 childNode .SetPreviousNode (lastNode )
118+ childNode .setParentNode (lastNode .GetParent ())
117119 lastNode .SetNextNode (childNode )
118120}
119121
120122// Append inserts the newNode to end of the node chain.
121123func (node * Node ) Append (newNode * Node ) {
122124 lastNode := node .GetLastNode ()
123125 newNode .SetPreviousNode (lastNode )
126+ newNode .setParentNode (lastNode .GetParent ())
124127 lastNode .SetNextNode (newNode )
125128}
126129
127130// GetParent returns a pointer to the parent node.
128131func (node * Node ) GetParent () * Node {
129- return node .GetFirstNode (). getParentNode ()
132+ return node .parentNode
130133}
131134
132135// GetLastNode returns the last node in the node branch.
@@ -203,3 +206,21 @@ func (node *Node) RemoveNode() {
203206func (node * Node ) IsTextNode () bool {
204207 return node .GetTagName () == ""
205208}
209+
210+ // Closest traverses the node tree and its parents (heading toward the root node) until it finds a node that matches the selector and returns that node.
211+ // Adapted from [https://developer.mozilla.org/en-US/docs/Web/API/Element/closest](MDN Element: closest() method)
212+ func (node * Node ) Closest (selector string ) * Node {
213+ traverser := NewTraverser (node )
214+ selectors := TokenizeSelectorsAndCombinators (selector )
215+
216+ for traverser .GetCurrentNode () != nil {
217+ if matchFromRightMostSelectors (traverser .GetCurrentNode (), selectors ) {
218+ break
219+ } else if traverser .GetCurrentNode ().GetPreviousNode () == nil {
220+ traverser .SetCurrentNodeTo (traverser .GetCurrentNode ().GetParent ())
221+ } else {
222+ traverser .Previous ()
223+ }
224+ }
225+ return traverser .GetCurrentNode ()
226+ }
0 commit comments