From f461c820306f41774eeb51e2ac8a6886f98a4db8 Mon Sep 17 00:00:00 2001 From: Martin Angers Date: Tue, 4 Sep 2012 10:58:44 -0400 Subject: [PATCH] add ParentsFilteredUntil...() with tests --- doc.go | 6 +++--- traversal.go | 38 ++++++++++++++++++++++++++++++++++++++ traversal_test.go | 19 +++++++++++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/doc.go b/doc.go index 6526569..7c19c49 100644 --- a/doc.go +++ b/doc.go @@ -138,9 +138,9 @@ package goquery // - NextAll() - Tree traversal // - NextUntil() - Tree traversal // x Not() -// - Parent() - Tree traversal -// - Parents() - Tree traversal -// - ParentsUntil() - Tree traversal +// x Parent() - Tree traversal +// x Parents() - Tree traversal +// x ParentsUntil() - Tree traversal // - Prev() - Tree traversal // - PrevAll() - Tree traversal // - PrevUntil() - Tree traversal diff --git a/traversal.go b/traversal.go index 53af58c..758a63b 100644 --- a/traversal.go +++ b/traversal.go @@ -140,6 +140,44 @@ func (this *Selection) ParentsUntilNodes(nodes ...*html.Node) *Selection { return pushStack(this, getParentsNodes(this.Nodes, "", nodes)) } +// ParentsFilteredUntil() is like ParentsUntil(), with the option to filter the +// results based on a selector string. It returns a new Selection +// object containing the matched elements. +func (this *Selection) ParentsFilteredUntil(filterSelector string, untilSelector string) *Selection { + + // Get the ParentsUntil() unfiltered + nodes := getParentsNodes(this.Nodes, untilSelector, nil) + // Create a temporary Selection to filter using winnow + sel := &Selection{nodes, this.document, nil} + // Filter based on selector + nodes = winnow(sel, filterSelector, true) + return pushStack(this, nodes) +} + +// ParentsFilteredUntilSelection() is like ParentsUntilSelection(), with the +// option to filter the results based on a selector string. It returns a new +// Selection object containing the matched elements. +func (this *Selection) ParentsFilteredUntilSelection(filterSelector string, sel *Selection) *Selection { + if sel == nil { + return this.ParentsFiltered(filterSelector) + } + return this.ParentsFilteredUntilNodes(filterSelector, sel.Nodes...) +} + +// ParentsFilteredUntilNodes() is like ParentsUntilNodes(), with the +// option to filter the results based on a selector string. It returns a new +// Selection object containing the matched elements. +func (this *Selection) ParentsFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection { + + // Get the ParentsUntilNodes() unfiltered + n := getParentsNodes(this.Nodes, "", nodes) + // Create a temporary Selection to filter using winnow + sel := &Selection{n, this.document, nil} + // Filter based on selector + n = winnow(sel, filterSelector, true) + return pushStack(this, n) +} + // Internal implementation to get all parent nodes, stopping at the specified // node (or nil if no stop). func getParentsNodes(nodes []*html.Node, stopSelector string, stopNodes []*html.Node) []*html.Node { diff --git a/traversal_test.go b/traversal_test.go index b1561d4..f76906b 100644 --- a/traversal_test.go +++ b/traversal_test.go @@ -93,3 +93,22 @@ func TestParentsUntilNodes(t *testing.T) { sel = sel.ParentsUntilNodes(sel2.Nodes...) AssertLength(t, sel.Nodes, 2) } + +func TestParentsFilteredUntil(t *testing.T) { + sel := Doc().Root.Find(".container-fluid").ParentsFilteredUntil(".pvk-content", "body") + AssertLength(t, sel.Nodes, 2) +} + +func TestParentsFilteredUntilSelection(t *testing.T) { + sel := Doc().Root.Find(".container-fluid") + sel2 := Doc().Root.Find(".row-fluid") + sel = sel.ParentsFilteredUntilSelection("div", sel2) + AssertLength(t, sel.Nodes, 3) +} + +func TestParentsFilteredUntilNodes(t *testing.T) { + sel := Doc().Root.Find(".container-fluid") + sel2 := Doc().Root.Find(".row-fluid") + sel = sel.ParentsFilteredUntilNodes("body", sel2.Nodes...) + AssertLength(t, sel.Nodes, 1) +}