github.com/godaddy-x/freego@v1.0.156/goquery/traversal.go (about)

     1  package goquery
     2  
     3  import "golang.org/x/net/html"
     4  
     5  type siblingType int
     6  
     7  // Sibling type, used internally when iterating over children at the same
     8  // level (siblings) to specify which nodes are requested.
     9  const (
    10  	siblingPrevUntil siblingType = iota - 3
    11  	siblingPrevAll
    12  	siblingPrev
    13  	siblingAll
    14  	siblingNext
    15  	siblingNextAll
    16  	siblingNextUntil
    17  	siblingAllIncludingNonElements
    18  )
    19  
    20  // Find gets the descendants of each element in the current set of matched
    21  // elements, filtered by a selector. It returns a new Selection object
    22  // containing these matched elements.
    23  func (s *Selection) Find(selector string) *Selection {
    24  	return pushStack(s, findWithMatcher(s.Nodes, compileMatcher(selector)))
    25  }
    26  
    27  // FindMatcher gets the descendants of each element in the current set of matched
    28  // elements, filtered by the matcher. It returns a new Selection object
    29  // containing these matched elements.
    30  func (s *Selection) FindMatcher(m Matcher) *Selection {
    31  	return pushStack(s, findWithMatcher(s.Nodes, m))
    32  }
    33  
    34  // FindSelection gets the descendants of each element in the current
    35  // Selection, filtered by a Selection. It returns a new Selection object
    36  // containing these matched elements.
    37  func (s *Selection) FindSelection(sel *Selection) *Selection {
    38  	if sel == nil {
    39  		return pushStack(s, nil)
    40  	}
    41  	return s.FindNodes(sel.Nodes...)
    42  }
    43  
    44  // FindNodes gets the descendants of each element in the current
    45  // Selection, filtered by some nodes. It returns a new Selection object
    46  // containing these matched elements.
    47  func (s *Selection) FindNodes(nodes ...*html.Node) *Selection {
    48  	return pushStack(s, mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
    49  		if sliceContains(s.Nodes, n) {
    50  			return []*html.Node{n}
    51  		}
    52  		return nil
    53  	}))
    54  }
    55  
    56  // Contents gets the children of each element in the Selection,
    57  // including text and comment nodes. It returns a new Selection object
    58  // containing these elements.
    59  func (s *Selection) Contents() *Selection {
    60  	return pushStack(s, getChildrenNodes(s.Nodes, siblingAllIncludingNonElements))
    61  }
    62  
    63  // ContentsFiltered gets the children of each element in the Selection,
    64  // filtered by the specified selector. It returns a new Selection
    65  // object containing these elements. Since selectors only act on Element nodes,
    66  // this function is an alias to ChildrenFiltered unless the selector is empty,
    67  // in which case it is an alias to Contents.
    68  func (s *Selection) ContentsFiltered(selector string) *Selection {
    69  	if selector != "" {
    70  		return s.ChildrenFiltered(selector)
    71  	}
    72  	return s.Contents()
    73  }
    74  
    75  // ContentsMatcher gets the children of each element in the Selection,
    76  // filtered by the specified matcher. It returns a new Selection
    77  // object containing these elements. Since matchers only act on Element nodes,
    78  // this function is an alias to ChildrenMatcher.
    79  func (s *Selection) ContentsMatcher(m Matcher) *Selection {
    80  	return s.ChildrenMatcher(m)
    81  }
    82  
    83  // Children gets the child elements of each element in the Selection.
    84  // It returns a new Selection object containing these elements.
    85  func (s *Selection) Children() *Selection {
    86  	return pushStack(s, getChildrenNodes(s.Nodes, siblingAll))
    87  }
    88  
    89  // ChildrenFiltered gets the child elements of each element in the Selection,
    90  // filtered by the specified selector. It returns a new
    91  // Selection object containing these elements.
    92  func (s *Selection) ChildrenFiltered(selector string) *Selection {
    93  	return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), compileMatcher(selector))
    94  }
    95  
    96  // ChildrenMatcher gets the child elements of each element in the Selection,
    97  // filtered by the specified matcher. It returns a new
    98  // Selection object containing these elements.
    99  func (s *Selection) ChildrenMatcher(m Matcher) *Selection {
   100  	return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), m)
   101  }
   102  
   103  // Parent gets the parent of each element in the Selection. It returns a
   104  // new Selection object containing the matched elements.
   105  func (s *Selection) Parent() *Selection {
   106  	return pushStack(s, getParentNodes(s.Nodes))
   107  }
   108  
   109  // ParentFiltered gets the parent of each element in the Selection filtered by a
   110  // selector. It returns a new Selection object containing the matched elements.
   111  func (s *Selection) ParentFiltered(selector string) *Selection {
   112  	return filterAndPush(s, getParentNodes(s.Nodes), compileMatcher(selector))
   113  }
   114  
   115  // ParentMatcher gets the parent of each element in the Selection filtered by a
   116  // matcher. It returns a new Selection object containing the matched elements.
   117  func (s *Selection) ParentMatcher(m Matcher) *Selection {
   118  	return filterAndPush(s, getParentNodes(s.Nodes), m)
   119  }
   120  
   121  // Closest gets the first element that matches the selector by testing the
   122  // element itself and traversing up through its ancestors in the DOM tree.
   123  func (s *Selection) Closest(selector string) *Selection {
   124  	cs := compileMatcher(selector)
   125  	return s.ClosestMatcher(cs)
   126  }
   127  
   128  // ClosestMatcher gets the first element that matches the matcher by testing the
   129  // element itself and traversing up through its ancestors in the DOM tree.
   130  func (s *Selection) ClosestMatcher(m Matcher) *Selection {
   131  	return pushStack(s, mapNodes(s.Nodes, func(i int, n *html.Node) []*html.Node {
   132  		// For each node in the selection, test the node itself, then each parent
   133  		// until a match is found.
   134  		for ; n != nil; n = n.Parent {
   135  			if m.Match(n) {
   136  				return []*html.Node{n}
   137  			}
   138  		}
   139  		return nil
   140  	}))
   141  }
   142  
   143  // ClosestNodes gets the first element that matches one of the nodes by testing the
   144  // element itself and traversing up through its ancestors in the DOM tree.
   145  func (s *Selection) ClosestNodes(nodes ...*html.Node) *Selection {
   146  	set := make(map[*html.Node]bool)
   147  	for _, n := range nodes {
   148  		set[n] = true
   149  	}
   150  	return pushStack(s, mapNodes(s.Nodes, func(i int, n *html.Node) []*html.Node {
   151  		// For each node in the selection, test the node itself, then each parent
   152  		// until a match is found.
   153  		for ; n != nil; n = n.Parent {
   154  			if set[n] {
   155  				return []*html.Node{n}
   156  			}
   157  		}
   158  		return nil
   159  	}))
   160  }
   161  
   162  // ClosestSelection gets the first element that matches one of the nodes in the
   163  // Selection by testing the element itself and traversing up through its ancestors
   164  // in the DOM tree.
   165  func (s *Selection) ClosestSelection(sel *Selection) *Selection {
   166  	if sel == nil {
   167  		return pushStack(s, nil)
   168  	}
   169  	return s.ClosestNodes(sel.Nodes...)
   170  }
   171  
   172  // Parents gets the ancestors of each element in the current Selection. It
   173  // returns a new Selection object with the matched elements.
   174  func (s *Selection) Parents() *Selection {
   175  	return pushStack(s, getParentsNodes(s.Nodes, nil, nil))
   176  }
   177  
   178  // ParentsFiltered gets the ancestors of each element in the current
   179  // Selection. It returns a new Selection object with the matched elements.
   180  func (s *Selection) ParentsFiltered(selector string) *Selection {
   181  	return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), compileMatcher(selector))
   182  }
   183  
   184  // ParentsMatcher gets the ancestors of each element in the current
   185  // Selection. It returns a new Selection object with the matched elements.
   186  func (s *Selection) ParentsMatcher(m Matcher) *Selection {
   187  	return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), m)
   188  }
   189  
   190  // ParentsUntil gets the ancestors of each element in the Selection, up to but
   191  // not including the element matched by the selector. It returns a new Selection
   192  // object containing the matched elements.
   193  func (s *Selection) ParentsUntil(selector string) *Selection {
   194  	return pushStack(s, getParentsNodes(s.Nodes, compileMatcher(selector), nil))
   195  }
   196  
   197  // ParentsUntilMatcher gets the ancestors of each element in the Selection, up to but
   198  // not including the element matched by the matcher. It returns a new Selection
   199  // object containing the matched elements.
   200  func (s *Selection) ParentsUntilMatcher(m Matcher) *Selection {
   201  	return pushStack(s, getParentsNodes(s.Nodes, m, nil))
   202  }
   203  
   204  // ParentsUntilSelection gets the ancestors of each element in the Selection,
   205  // up to but not including the elements in the specified Selection. It returns a
   206  // new Selection object containing the matched elements.
   207  func (s *Selection) ParentsUntilSelection(sel *Selection) *Selection {
   208  	if sel == nil {
   209  		return s.Parents()
   210  	}
   211  	return s.ParentsUntilNodes(sel.Nodes...)
   212  }
   213  
   214  // ParentsUntilNodes gets the ancestors of each element in the Selection,
   215  // up to but not including the specified nodes. It returns a
   216  // new Selection object containing the matched elements.
   217  func (s *Selection) ParentsUntilNodes(nodes ...*html.Node) *Selection {
   218  	return pushStack(s, getParentsNodes(s.Nodes, nil, nodes))
   219  }
   220  
   221  // ParentsFilteredUntil is like ParentsUntil, with the option to filter the
   222  // results based on a selector string. It returns a new Selection
   223  // object containing the matched elements.
   224  func (s *Selection) ParentsFilteredUntil(filterSelector, untilSelector string) *Selection {
   225  	return filterAndPush(s, getParentsNodes(s.Nodes, compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
   226  }
   227  
   228  // ParentsFilteredUntilMatcher is like ParentsUntilMatcher, with the option to filter the
   229  // results based on a matcher. It returns a new Selection object containing the matched elements.
   230  func (s *Selection) ParentsFilteredUntilMatcher(filter, until Matcher) *Selection {
   231  	return filterAndPush(s, getParentsNodes(s.Nodes, until, nil), filter)
   232  }
   233  
   234  // ParentsFilteredUntilSelection is like ParentsUntilSelection, with the
   235  // option to filter the results based on a selector string. It returns a new
   236  // Selection object containing the matched elements.
   237  func (s *Selection) ParentsFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
   238  	return s.ParentsMatcherUntilSelection(compileMatcher(filterSelector), sel)
   239  }
   240  
   241  // ParentsMatcherUntilSelection is like ParentsUntilSelection, with the
   242  // option to filter the results based on a matcher. It returns a new
   243  // Selection object containing the matched elements.
   244  func (s *Selection) ParentsMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
   245  	if sel == nil {
   246  		return s.ParentsMatcher(filter)
   247  	}
   248  	return s.ParentsMatcherUntilNodes(filter, sel.Nodes...)
   249  }
   250  
   251  // ParentsFilteredUntilNodes is like ParentsUntilNodes, with the
   252  // option to filter the results based on a selector string. It returns a new
   253  // Selection object containing the matched elements.
   254  func (s *Selection) ParentsFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
   255  	return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), compileMatcher(filterSelector))
   256  }
   257  
   258  // ParentsMatcherUntilNodes is like ParentsUntilNodes, with the
   259  // option to filter the results based on a matcher. It returns a new
   260  // Selection object containing the matched elements.
   261  func (s *Selection) ParentsMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
   262  	return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), filter)
   263  }
   264  
   265  // Siblings gets the siblings of each element in the Selection. It returns
   266  // a new Selection object containing the matched elements.
   267  func (s *Selection) Siblings() *Selection {
   268  	return pushStack(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil))
   269  }
   270  
   271  // SiblingsFiltered gets the siblings of each element in the Selection
   272  // filtered by a selector. It returns a new Selection object containing the
   273  // matched elements.
   274  func (s *Selection) SiblingsFiltered(selector string) *Selection {
   275  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), compileMatcher(selector))
   276  }
   277  
   278  // SiblingsMatcher gets the siblings of each element in the Selection
   279  // filtered by a matcher. It returns a new Selection object containing the
   280  // matched elements.
   281  func (s *Selection) SiblingsMatcher(m Matcher) *Selection {
   282  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), m)
   283  }
   284  
   285  // Next gets the immediately following sibling of each element in the
   286  // Selection. It returns a new Selection object containing the matched elements.
   287  func (s *Selection) Next() *Selection {
   288  	return pushStack(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil))
   289  }
   290  
   291  // NextFiltered gets the immediately following sibling of each element in the
   292  // Selection filtered by a selector. It returns a new Selection object
   293  // containing the matched elements.
   294  func (s *Selection) NextFiltered(selector string) *Selection {
   295  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), compileMatcher(selector))
   296  }
   297  
   298  // NextMatcher gets the immediately following sibling of each element in the
   299  // Selection filtered by a matcher. It returns a new Selection object
   300  // containing the matched elements.
   301  func (s *Selection) NextMatcher(m Matcher) *Selection {
   302  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), m)
   303  }
   304  
   305  // NextAll gets all the following siblings of each element in the
   306  // Selection. It returns a new Selection object containing the matched elements.
   307  func (s *Selection) NextAll() *Selection {
   308  	return pushStack(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil))
   309  }
   310  
   311  // NextAllFiltered gets all the following siblings of each element in the
   312  // Selection filtered by a selector. It returns a new Selection object
   313  // containing the matched elements.
   314  func (s *Selection) NextAllFiltered(selector string) *Selection {
   315  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), compileMatcher(selector))
   316  }
   317  
   318  // NextAllMatcher gets all the following siblings of each element in the
   319  // Selection filtered by a matcher. It returns a new Selection object
   320  // containing the matched elements.
   321  func (s *Selection) NextAllMatcher(m Matcher) *Selection {
   322  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), m)
   323  }
   324  
   325  // Prev gets the immediately preceding sibling of each element in the
   326  // Selection. It returns a new Selection object containing the matched elements.
   327  func (s *Selection) Prev() *Selection {
   328  	return pushStack(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil))
   329  }
   330  
   331  // PrevFiltered gets the immediately preceding sibling of each element in the
   332  // Selection filtered by a selector. It returns a new Selection object
   333  // containing the matched elements.
   334  func (s *Selection) PrevFiltered(selector string) *Selection {
   335  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), compileMatcher(selector))
   336  }
   337  
   338  // PrevMatcher gets the immediately preceding sibling of each element in the
   339  // Selection filtered by a matcher. It returns a new Selection object
   340  // containing the matched elements.
   341  func (s *Selection) PrevMatcher(m Matcher) *Selection {
   342  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), m)
   343  }
   344  
   345  // PrevAll gets all the preceding siblings of each element in the
   346  // Selection. It returns a new Selection object containing the matched elements.
   347  func (s *Selection) PrevAll() *Selection {
   348  	return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil))
   349  }
   350  
   351  // PrevAllFiltered gets all the preceding siblings of each element in the
   352  // Selection filtered by a selector. It returns a new Selection object
   353  // containing the matched elements.
   354  func (s *Selection) PrevAllFiltered(selector string) *Selection {
   355  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), compileMatcher(selector))
   356  }
   357  
   358  // PrevAllMatcher gets all the preceding siblings of each element in the
   359  // Selection filtered by a matcher. It returns a new Selection object
   360  // containing the matched elements.
   361  func (s *Selection) PrevAllMatcher(m Matcher) *Selection {
   362  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), m)
   363  }
   364  
   365  // NextUntil gets all following siblings of each element up to but not
   366  // including the element matched by the selector. It returns a new Selection
   367  // object containing the matched elements.
   368  func (s *Selection) NextUntil(selector string) *Selection {
   369  	return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
   370  		compileMatcher(selector), nil))
   371  }
   372  
   373  // NextUntilMatcher gets all following siblings of each element up to but not
   374  // including the element matched by the matcher. It returns a new Selection
   375  // object containing the matched elements.
   376  func (s *Selection) NextUntilMatcher(m Matcher) *Selection {
   377  	return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
   378  		m, nil))
   379  }
   380  
   381  // NextUntilSelection gets all following siblings of each element up to but not
   382  // including the element matched by the Selection. It returns a new Selection
   383  // object containing the matched elements.
   384  func (s *Selection) NextUntilSelection(sel *Selection) *Selection {
   385  	if sel == nil {
   386  		return s.NextAll()
   387  	}
   388  	return s.NextUntilNodes(sel.Nodes...)
   389  }
   390  
   391  // NextUntilNodes gets all following siblings of each element up to but not
   392  // including the element matched by the nodes. It returns a new Selection
   393  // object containing the matched elements.
   394  func (s *Selection) NextUntilNodes(nodes ...*html.Node) *Selection {
   395  	return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
   396  		nil, nodes))
   397  }
   398  
   399  // PrevUntil gets all preceding siblings of each element up to but not
   400  // including the element matched by the selector. It returns a new Selection
   401  // object containing the matched elements.
   402  func (s *Selection) PrevUntil(selector string) *Selection {
   403  	return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
   404  		compileMatcher(selector), nil))
   405  }
   406  
   407  // PrevUntilMatcher gets all preceding siblings of each element up to but not
   408  // including the element matched by the matcher. It returns a new Selection
   409  // object containing the matched elements.
   410  func (s *Selection) PrevUntilMatcher(m Matcher) *Selection {
   411  	return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
   412  		m, nil))
   413  }
   414  
   415  // PrevUntilSelection gets all preceding siblings of each element up to but not
   416  // including the element matched by the Selection. It returns a new Selection
   417  // object containing the matched elements.
   418  func (s *Selection) PrevUntilSelection(sel *Selection) *Selection {
   419  	if sel == nil {
   420  		return s.PrevAll()
   421  	}
   422  	return s.PrevUntilNodes(sel.Nodes...)
   423  }
   424  
   425  // PrevUntilNodes gets all preceding siblings of each element up to but not
   426  // including the element matched by the nodes. It returns a new Selection
   427  // object containing the matched elements.
   428  func (s *Selection) PrevUntilNodes(nodes ...*html.Node) *Selection {
   429  	return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
   430  		nil, nodes))
   431  }
   432  
   433  // NextFilteredUntil is like NextUntil, with the option to filter
   434  // the results based on a selector string.
   435  // It returns a new Selection object containing the matched elements.
   436  func (s *Selection) NextFilteredUntil(filterSelector, untilSelector string) *Selection {
   437  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
   438  		compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
   439  }
   440  
   441  // NextFilteredUntilMatcher is like NextUntilMatcher, with the option to filter
   442  // the results based on a matcher.
   443  // It returns a new Selection object containing the matched elements.
   444  func (s *Selection) NextFilteredUntilMatcher(filter, until Matcher) *Selection {
   445  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
   446  		until, nil), filter)
   447  }
   448  
   449  // NextFilteredUntilSelection is like NextUntilSelection, with the
   450  // option to filter the results based on a selector string. It returns a new
   451  // Selection object containing the matched elements.
   452  func (s *Selection) NextFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
   453  	return s.NextMatcherUntilSelection(compileMatcher(filterSelector), sel)
   454  }
   455  
   456  // NextMatcherUntilSelection is like NextUntilSelection, with the
   457  // option to filter the results based on a matcher. It returns a new
   458  // Selection object containing the matched elements.
   459  func (s *Selection) NextMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
   460  	if sel == nil {
   461  		return s.NextMatcher(filter)
   462  	}
   463  	return s.NextMatcherUntilNodes(filter, sel.Nodes...)
   464  }
   465  
   466  // NextFilteredUntilNodes is like NextUntilNodes, with the
   467  // option to filter the results based on a selector string. It returns a new
   468  // Selection object containing the matched elements.
   469  func (s *Selection) NextFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
   470  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
   471  		nil, nodes), compileMatcher(filterSelector))
   472  }
   473  
   474  // NextMatcherUntilNodes is like NextUntilNodes, with the
   475  // option to filter the results based on a matcher. It returns a new
   476  // Selection object containing the matched elements.
   477  func (s *Selection) NextMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
   478  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
   479  		nil, nodes), filter)
   480  }
   481  
   482  // PrevFilteredUntil is like PrevUntil, with the option to filter
   483  // the results based on a selector string.
   484  // It returns a new Selection object containing the matched elements.
   485  func (s *Selection) PrevFilteredUntil(filterSelector, untilSelector string) *Selection {
   486  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
   487  		compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
   488  }
   489  
   490  // PrevFilteredUntilMatcher is like PrevUntilMatcher, with the option to filter
   491  // the results based on a matcher.
   492  // It returns a new Selection object containing the matched elements.
   493  func (s *Selection) PrevFilteredUntilMatcher(filter, until Matcher) *Selection {
   494  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
   495  		until, nil), filter)
   496  }
   497  
   498  // PrevFilteredUntilSelection is like PrevUntilSelection, with the
   499  // option to filter the results based on a selector string. It returns a new
   500  // Selection object containing the matched elements.
   501  func (s *Selection) PrevFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
   502  	return s.PrevMatcherUntilSelection(compileMatcher(filterSelector), sel)
   503  }
   504  
   505  // PrevMatcherUntilSelection is like PrevUntilSelection, with the
   506  // option to filter the results based on a matcher. It returns a new
   507  // Selection object containing the matched elements.
   508  func (s *Selection) PrevMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
   509  	if sel == nil {
   510  		return s.PrevMatcher(filter)
   511  	}
   512  	return s.PrevMatcherUntilNodes(filter, sel.Nodes...)
   513  }
   514  
   515  // PrevFilteredUntilNodes is like PrevUntilNodes, with the
   516  // option to filter the results based on a selector string. It returns a new
   517  // Selection object containing the matched elements.
   518  func (s *Selection) PrevFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
   519  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
   520  		nil, nodes), compileMatcher(filterSelector))
   521  }
   522  
   523  // PrevMatcherUntilNodes is like PrevUntilNodes, with the
   524  // option to filter the results based on a matcher. It returns a new
   525  // Selection object containing the matched elements.
   526  func (s *Selection) PrevMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
   527  	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
   528  		nil, nodes), filter)
   529  }
   530  
   531  // Filter and push filters the nodes based on a matcher, and pushes the results
   532  // on the stack, with the srcSel as previous selection.
   533  func filterAndPush(srcSel *Selection, nodes []*html.Node, m Matcher) *Selection {
   534  	// Create a temporary Selection with the specified nodes to filter using winnow
   535  	sel := &Selection{nodes, srcSel.document, nil}
   536  	// Filter based on matcher and push on stack
   537  	return pushStack(srcSel, winnow(sel, m, true))
   538  }
   539  
   540  // Internal implementation of Find that return raw nodes.
   541  func findWithMatcher(nodes []*html.Node, m Matcher) []*html.Node {
   542  	// Map nodes to find the matches within the children of each node
   543  	return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
   544  		// Go down one level, becausejQuery's Find selects only within descendants
   545  		for c := n.FirstChild; c != nil; c = c.NextSibling {
   546  			if c.Type == html.ElementNode {
   547  				result = append(result, m.MatchAll(c)...)
   548  			}
   549  		}
   550  		return
   551  	})
   552  }
   553  
   554  // Internal implementation to get all parent nodes, stopping at the specified
   555  // node (or nil if no stop).
   556  func getParentsNodes(nodes []*html.Node, stopm Matcher, stopNodes []*html.Node) []*html.Node {
   557  	return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
   558  		for p := n.Parent; p != nil; p = p.Parent {
   559  			sel := newSingleSelection(p, nil)
   560  			if stopm != nil {
   561  				if sel.IsMatcher(stopm) {
   562  					break
   563  				}
   564  			} else if len(stopNodes) > 0 {
   565  				if sel.IsNodes(stopNodes...) {
   566  					break
   567  				}
   568  			}
   569  			if p.Type == html.ElementNode {
   570  				result = append(result, p)
   571  			}
   572  		}
   573  		return
   574  	})
   575  }
   576  
   577  // Internal implementation of sibling nodes that return a raw slice of matches.
   578  func getSiblingNodes(nodes []*html.Node, st siblingType, untilm Matcher, untilNodes []*html.Node) []*html.Node {
   579  	var f func(*html.Node) bool
   580  
   581  	// If the requested siblings are ...Until, create the test function to
   582  	// determine if the until condition is reached (returns true if it is)
   583  	if st == siblingNextUntil || st == siblingPrevUntil {
   584  		f = func(n *html.Node) bool {
   585  			if untilm != nil {
   586  				// Matcher-based condition
   587  				sel := newSingleSelection(n, nil)
   588  				return sel.IsMatcher(untilm)
   589  			} else if len(untilNodes) > 0 {
   590  				// Nodes-based condition
   591  				sel := newSingleSelection(n, nil)
   592  				return sel.IsNodes(untilNodes...)
   593  			}
   594  			return false
   595  		}
   596  	}
   597  
   598  	return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
   599  		return getChildrenWithSiblingType(n.Parent, st, n, f)
   600  	})
   601  }
   602  
   603  // Gets the children nodes of each node in the specified slice of nodes,
   604  // based on the sibling type request.
   605  func getChildrenNodes(nodes []*html.Node, st siblingType) []*html.Node {
   606  	return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
   607  		return getChildrenWithSiblingType(n, st, nil, nil)
   608  	})
   609  }
   610  
   611  // Gets the children of the specified parent, based on the requested sibling
   612  // type, skipping a specified node if required.
   613  func getChildrenWithSiblingType(parent *html.Node, st siblingType, skipNode *html.Node,
   614  	untilFunc func(*html.Node) bool) (result []*html.Node) {
   615  
   616  	// Create the iterator function
   617  	var iter = func(cur *html.Node) (ret *html.Node) {
   618  		// Based on the sibling type requested, iterate the right way
   619  		for {
   620  			switch st {
   621  			case siblingAll, siblingAllIncludingNonElements:
   622  				if cur == nil {
   623  					// First iteration, start with first child of parent
   624  					// Skip node if required
   625  					if ret = parent.FirstChild; ret == skipNode && skipNode != nil {
   626  						ret = skipNode.NextSibling
   627  					}
   628  				} else {
   629  					// Skip node if required
   630  					if ret = cur.NextSibling; ret == skipNode && skipNode != nil {
   631  						ret = skipNode.NextSibling
   632  					}
   633  				}
   634  			case siblingPrev, siblingPrevAll, siblingPrevUntil:
   635  				if cur == nil {
   636  					// Start with previous sibling of the skip node
   637  					ret = skipNode.PrevSibling
   638  				} else {
   639  					ret = cur.PrevSibling
   640  				}
   641  			case siblingNext, siblingNextAll, siblingNextUntil:
   642  				if cur == nil {
   643  					// Start with next sibling of the skip node
   644  					ret = skipNode.NextSibling
   645  				} else {
   646  					ret = cur.NextSibling
   647  				}
   648  			default:
   649  				panic("Invalid sibling type.")
   650  			}
   651  			if ret == nil || ret.Type == html.ElementNode || st == siblingAllIncludingNonElements {
   652  				return
   653  			}
   654  			// Not a valid node, try again from this one
   655  			cur = ret
   656  		}
   657  	}
   658  
   659  	for c := iter(nil); c != nil; c = iter(c) {
   660  		// If this is an ...Until case, test before append (returns true
   661  		// if the until condition is reached)
   662  		if st == siblingNextUntil || st == siblingPrevUntil {
   663  			if untilFunc(c) {
   664  				return
   665  			}
   666  		}
   667  		result = append(result, c)
   668  		if st == siblingNext || st == siblingPrev {
   669  			// Only one node was requested (immediate next or previous), so exit
   670  			return
   671  		}
   672  	}
   673  	return
   674  }
   675  
   676  // Internal implementation of parent nodes that return a raw slice of Nodes.
   677  func getParentNodes(nodes []*html.Node) []*html.Node {
   678  	return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
   679  		if n.Parent != nil && n.Parent.Type == html.ElementNode {
   680  			return []*html.Node{n.Parent}
   681  		}
   682  		return nil
   683  	})
   684  }
   685  
   686  // Internal map function used by many traversing methods. Takes the source nodes
   687  // to iterate on and the mapping function that returns an array of nodes.
   688  // Returns an array of nodes mapped by calling the callback function once for
   689  // each node in the source nodes.
   690  func mapNodes(nodes []*html.Node, f func(int, *html.Node) []*html.Node) (result []*html.Node) {
   691  	set := make(map[*html.Node]bool)
   692  	for i, n := range nodes {
   693  		if vals := f(i, n); len(vals) > 0 {
   694  			result = appendWithoutDuplicates(result, vals, set)
   695  		}
   696  	}
   697  	return result
   698  }