1package goquery 2 3import "golang.org/x/net/html" 4 5// Filter reduces the set of matched elements to those that match the selector string. 6// It returns a new Selection object for this subset of matching elements. 7func (s *Selection) Filter(selector string) *Selection { 8 return s.FilterMatcher(compileMatcher(selector)) 9} 10 11// FilterMatcher reduces the set of matched elements to those that match 12// the given matcher. It returns a new Selection object for this subset 13// of matching elements. 14func (s *Selection) FilterMatcher(m Matcher) *Selection { 15 return pushStack(s, winnow(s, m, true)) 16} 17 18// Not removes elements from the Selection that match the selector string. 19// It returns a new Selection object with the matching elements removed. 20func (s *Selection) Not(selector string) *Selection { 21 return s.NotMatcher(compileMatcher(selector)) 22} 23 24// NotMatcher removes elements from the Selection that match the given matcher. 25// It returns a new Selection object with the matching elements removed. 26func (s *Selection) NotMatcher(m Matcher) *Selection { 27 return pushStack(s, winnow(s, m, false)) 28} 29 30// FilterFunction reduces the set of matched elements to those that pass the function's test. 31// It returns a new Selection object for this subset of elements. 32func (s *Selection) FilterFunction(f func(int, *Selection) bool) *Selection { 33 return pushStack(s, winnowFunction(s, f, true)) 34} 35 36// NotFunction removes elements from the Selection that pass the function's test. 37// It returns a new Selection object with the matching elements removed. 38func (s *Selection) NotFunction(f func(int, *Selection) bool) *Selection { 39 return pushStack(s, winnowFunction(s, f, false)) 40} 41 42// FilterNodes reduces the set of matched elements to those that match the specified nodes. 43// It returns a new Selection object for this subset of elements. 44func (s *Selection) FilterNodes(nodes ...*html.Node) *Selection { 45 return pushStack(s, winnowNodes(s, nodes, true)) 46} 47 48// NotNodes removes elements from the Selection that match the specified nodes. 49// It returns a new Selection object with the matching elements removed. 50func (s *Selection) NotNodes(nodes ...*html.Node) *Selection { 51 return pushStack(s, winnowNodes(s, nodes, false)) 52} 53 54// FilterSelection reduces the set of matched elements to those that match a 55// node in the specified Selection object. 56// It returns a new Selection object for this subset of elements. 57func (s *Selection) FilterSelection(sel *Selection) *Selection { 58 if sel == nil { 59 return pushStack(s, winnowNodes(s, nil, true)) 60 } 61 return pushStack(s, winnowNodes(s, sel.Nodes, true)) 62} 63 64// NotSelection removes elements from the Selection that match a node in the specified 65// Selection object. It returns a new Selection object with the matching elements removed. 66func (s *Selection) NotSelection(sel *Selection) *Selection { 67 if sel == nil { 68 return pushStack(s, winnowNodes(s, nil, false)) 69 } 70 return pushStack(s, winnowNodes(s, sel.Nodes, false)) 71} 72 73// Intersection is an alias for FilterSelection. 74func (s *Selection) Intersection(sel *Selection) *Selection { 75 return s.FilterSelection(sel) 76} 77 78// Has reduces the set of matched elements to those that have a descendant 79// that matches the selector. 80// It returns a new Selection object with the matching elements. 81func (s *Selection) Has(selector string) *Selection { 82 return s.HasSelection(s.document.Find(selector)) 83} 84 85// HasMatcher reduces the set of matched elements to those that have a descendant 86// that matches the matcher. 87// It returns a new Selection object with the matching elements. 88func (s *Selection) HasMatcher(m Matcher) *Selection { 89 return s.HasSelection(s.document.FindMatcher(m)) 90} 91 92// HasNodes reduces the set of matched elements to those that have a 93// descendant that matches one of the nodes. 94// It returns a new Selection object with the matching elements. 95func (s *Selection) HasNodes(nodes ...*html.Node) *Selection { 96 return s.FilterFunction(func(_ int, sel *Selection) bool { 97 // Add all nodes that contain one of the specified nodes 98 for _, n := range nodes { 99 if sel.Contains(n) { 100 return true 101 } 102 } 103 return false 104 }) 105} 106 107// HasSelection reduces the set of matched elements to those that have a 108// descendant that matches one of the nodes of the specified Selection object. 109// It returns a new Selection object with the matching elements. 110func (s *Selection) HasSelection(sel *Selection) *Selection { 111 if sel == nil { 112 return s.HasNodes() 113 } 114 return s.HasNodes(sel.Nodes...) 115} 116 117// End ends the most recent filtering operation in the current chain and 118// returns the set of matched elements to its previous state. 119func (s *Selection) End() *Selection { 120 if s.prevSel != nil { 121 return s.prevSel 122 } 123 return newEmptySelection(s.document) 124} 125 126// Filter based on the matcher, and the indicator to keep (Filter) or 127// to get rid of (Not) the matching elements. 128func winnow(sel *Selection, m Matcher, keep bool) []*html.Node { 129 // Optimize if keep is requested 130 if keep { 131 return m.Filter(sel.Nodes) 132 } 133 // Use grep 134 return grep(sel, func(i int, s *Selection) bool { 135 return !m.Match(s.Get(0)) 136 }) 137} 138 139// Filter based on an array of nodes, and the indicator to keep (Filter) or 140// to get rid of (Not) the matching elements. 141func winnowNodes(sel *Selection, nodes []*html.Node, keep bool) []*html.Node { 142 if len(nodes)+len(sel.Nodes) < minNodesForSet { 143 return grep(sel, func(i int, s *Selection) bool { 144 return isInSlice(nodes, s.Get(0)) == keep 145 }) 146 } 147 148 set := make(map[*html.Node]bool) 149 for _, n := range nodes { 150 set[n] = true 151 } 152 return grep(sel, func(i int, s *Selection) bool { 153 return set[s.Get(0)] == keep 154 }) 155} 156 157// Filter based on a function test, and the indicator to keep (Filter) or 158// to get rid of (Not) the matching elements. 159func winnowFunction(sel *Selection, f func(int, *Selection) bool, keep bool) []*html.Node { 160 return grep(sel, func(i int, s *Selection) bool { 161 return f(i, s) == keep 162 }) 163} 164