work on filter.go, needs tests now

This commit is contained in:
Martin Angers
2012-08-30 22:47:12 -04:00
parent 503306d8a5
commit 437a1dc2a1
4 changed files with 81 additions and 50 deletions

View File

@@ -5,42 +5,98 @@ import (
"exp/html"
)
// Filter() reduces the set of matched elements to those that match the selector string.
// It returns a new Selection object for this subset of matching elements.
func (this *Selection) Filter(selector string) *Selection {
return pushStack(this, winnow(this, selector, true))
}
// Not() removes elements from the Selection that match the selector string.
// It returns a new Selection object with the matching elements removed.
func (this *Selection) Not(selector string) *Selection {
return pushStack(this, winnow(this, selector, false))
}
// FilterFunction() reduces the set of matched elements to those that pass the function's test.
// It returns a new Selection object for this subset of elements.
func (this *Selection) FilterFunction(f func(int, *Selection) bool) *Selection {
return pushStack(this, winnowFunction(this, f, true))
}
// Not() removes elements from the Selection that pass the function's test.
// It returns a new Selection object with the matching elements removed.
func (this *Selection) NotFunction(f func(int, *Selection) bool) *Selection {
return pushStack(this, winnowFunction(this, f, false))
}
// FilterNodes() reduces the set of matched elements to those that match the specified nodes.
// It returns a new Selection object for this subset of elements.
func (this *Selection) FilterNodes(nodes ...*html.Node) *Selection {
return pushStack(this, winnowNodes(this, nodes, true))
}
// Not() removes elements from the Selection that match the specified nodes.
// It returns a new Selection object with the matching elements removed.
func (this *Selection) NotNodes(nodes ...*html.Node) *Selection {
return pushStack(this, winnowNodes(this, nodes, false))
}
// FilterSelection() reduces the set of matched elements to those that match a node in the specified Selection object.
// It returns a new Selection object for this subset of elements.
func (this *Selection) FilterSelection(s *Selection) *Selection {
return pushStack(this, winnowNodes(this, s.Nodes, true))
}
// Not() removes elements from the Selection that match a node in the specified Selection object.
// It returns a new Selection object with the matching elements removed.
func (this *Selection) NotSelection(s *Selection) *Selection {
return pushStack(this, winnowNodes(this, s.Nodes, false))
}
// Union() is an alias for FilterSelection().
func (this *Selection) Union(s *Selection) *Selection {
return this.FilterSelection(s)
}
// Has() reduces the set of matched elements to those that have a descendant that matches the selector.
// It returns a new Selection object with the matching elements.
func (this *Selection) Has(selector string) *Selection {
sel := this.document.Find(selector)
return this.HasSelection(sel)
}
// HasNodes() reduces the set of matched elements to those that have a descendant that matches one of the nodes.
// It returns a new Selection object with the matching elements.
func (this *Selection) HasNodes(nodes ...*html.Node) *Selection {
return this.FilterFunction(func(_ int, s *Selection) bool {
// Add all nodes that contain one of the specified nodes
for _, n := range nodes {
if s.Contains(n) {
return true
}
}
return false
})
}
// HasSelection() reduces the set of matched elements to those that have a descendant that matches one of
// the nodes of the specified Selection object.
// It returns a new Selection object with the matching elements.
func (this *Selection) HasSelection(sel *Selection) *Selection {
return this.HasNodes(sel.Nodes...)
}
// End() ends the most recent filtering operation in the current chain and returns
// the set of matched elements to its previous state.
func (this *Selection) End() *Selection {
if this.prevSel != nil {
return this.prevSel
}
return newEmptySelection(this.document)
}
// Filter based on a selector string, and the indicator to keep (Filter) or
// to get rid of (Not) the matching elements.
func winnow(sel *Selection, selector string, keep bool) []*html.Node {
cs := cascadia.MustCompile(selector)
@@ -50,49 +106,24 @@ func winnow(sel *Selection, selector string, keep bool) []*html.Node {
} else {
// Use grep
return grep(sel, func(i int, s *Selection) bool {
return !cs(s.Get(0))
return !cs.Match(s.Get(0))
})
}
return nil
}
// Filter based on an array of nodes, and the indicator to keep (Filter) or
// to get rid of (Not) the matching elements.
func winnowNodes(sel *Selection, nodes []*html.Node, keep bool) []*html.Node {
return grep(sel, func(i int, s *Selection) bool {
return isInSlice(nodes, s.Get(0)) == keep
})
}
// Identical functionality for FilterFunction() and NotFunction(), only keep changes.
// Filter based on a function test, and the indicator to keep (Filter) or
// to get rid of (Not) the matching elements.
func winnowFunction(sel *Selection, f func(int, *Selection) bool, keep bool) []*html.Node {
return grep(sel, func(i int, s *Selection) bool {
return f(i, s) == keep
})
}
func (this *Selection) Has(selector string) *Selection {
sel := this.document.Find(selector)
return this.HasSelection(sel)
}
func (this *Selection) HasNode(node *html.Node) *Selection {
return this.FilterFunction(func(_ int, s *Selection) bool {
// Add all nodes that contain the node specified
if s.Contains(node) {
return true
}
return false
})
}
func (this *Selection) HasSelection(sel *Selection) *Selection {
return this.FilterFunction(func(_ int, s *Selection) bool {
// Add all nodes that contain one of the nodes in the selection
for _, n := range sel.Nodes {
if s.Contains(n) {
return true
}
}
return false
})
}