mirror of
https://github.com/PuerkitoBio/goquery
synced 2025-10-01 06:52:14 +08:00
add Contents() and Children() with tests.
This commit is contained in:
8
doc.go
8
doc.go
@@ -95,6 +95,9 @@ The various methods are split into files based on the category of behavior:
|
|||||||
*/
|
*/
|
||||||
package goquery
|
package goquery
|
||||||
|
|
||||||
|
// TODO : Test End() on all filtering/expanding/array/traversal functions, make
|
||||||
|
// sure it returns the same object as the previous selection.
|
||||||
|
|
||||||
// DONE array.go : Positional Manipulation: First(), Last(), Eq(), Get(), Index(), Slice()
|
// DONE array.go : Positional Manipulation: First(), Last(), Eq(), Get(), Index(), Slice()
|
||||||
// DONE filter.go : Filtering: Filter(), Not(), Has(), End()
|
// DONE filter.go : Filtering: Filter(), Not(), Has(), End()
|
||||||
// DONE expand.go : "Expanding": Add(), AndSelf()
|
// DONE expand.go : "Expanding": Add(), AndSelf()
|
||||||
@@ -115,7 +118,7 @@ package goquery
|
|||||||
// x Children()
|
// x Children()
|
||||||
// - Closest() - Tree Traversal
|
// - Closest() - Tree Traversal
|
||||||
// x Contains()
|
// x Contains()
|
||||||
// - Contents() (similar to Children(), but includes text and comment nodes, so Children() should filter them out) - Misc. Traversing
|
// x Contents()
|
||||||
// x Each()
|
// x Each()
|
||||||
// x End()
|
// x End()
|
||||||
// x Eq()
|
// x Eq()
|
||||||
@@ -125,7 +128,7 @@ package goquery
|
|||||||
// x Get()
|
// x Get()
|
||||||
// x Has()
|
// x Has()
|
||||||
// x HasClass()
|
// x HasClass()
|
||||||
// - Html() ? - Attributes
|
// x Html()
|
||||||
// x Index()
|
// x Index()
|
||||||
// x Is() - Filtering
|
// x Is() - Filtering
|
||||||
// x Last()
|
// x Last()
|
||||||
@@ -147,4 +150,3 @@ package goquery
|
|||||||
// x Text() - DOM Manipulation
|
// x Text() - DOM Manipulation
|
||||||
// x ToArray()
|
// x ToArray()
|
||||||
// x Unique() internally only
|
// x Unique() internally only
|
||||||
// - Val() ? - Attributes
|
|
||||||
|
@@ -21,6 +21,22 @@ func TestEach(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEachEmptySelection(t *testing.T) {
|
||||||
|
var cnt int
|
||||||
|
|
||||||
|
sel := Doc().Find("zzzz")
|
||||||
|
sel.Each(func(i int, n *Selection) {
|
||||||
|
cnt++
|
||||||
|
})
|
||||||
|
if cnt > 0 {
|
||||||
|
t.Error("Expected Each() to not be called on empty Selection.")
|
||||||
|
}
|
||||||
|
sel2 := sel.Find("div")
|
||||||
|
if sel2.Nodes != nil {
|
||||||
|
t.Error("Expected Find() on empty Selection to return an empty Selection.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMap(t *testing.T) {
|
func TestMap(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
vals := sel.Map(func(i int, s *Selection) string {
|
vals := sel.Map(func(i int, s *Selection) string {
|
||||||
|
57
traversal.go
57
traversal.go
@@ -3,7 +3,6 @@ package goquery
|
|||||||
import (
|
import (
|
||||||
"code.google.com/p/cascadia"
|
"code.google.com/p/cascadia"
|
||||||
"exp/html"
|
"exp/html"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO : Maybe make the Document's Root return a Selection, Find() on the
|
// TODO : Maybe make the Document's Root return a Selection, Find() on the
|
||||||
@@ -40,24 +39,52 @@ func findWithContext(selector string, nodes ...*html.Node) []*html.Node {
|
|||||||
return matches
|
return matches
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : Tests and doc for contents and children
|
// Contents() gets the children of each element in the Selection,
|
||||||
|
// including text and comment nodes. It returns a new Selection object
|
||||||
|
// containing these elements.
|
||||||
func (this *Selection) Contents() *Selection {
|
func (this *Selection) Contents() *Selection {
|
||||||
var matches []*html.Node
|
return pushStack(this, getSelectionChildren(this, false))
|
||||||
|
|
||||||
for _, n := range this.Nodes {
|
|
||||||
matches = appendWithoutDuplicates(matches, getChildren(n, false))
|
|
||||||
}
|
|
||||||
return pushStack(this, matches)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Selection) Children() *Selection {
|
// ContentsFiltered() gets the children of each element in the Selection,
|
||||||
var matches []*html.Node
|
// filtered by the specified selector. It returns a new Selection
|
||||||
|
// object containing these elements. Since selectors only act on Element nodes,
|
||||||
for _, n := range this.Nodes {
|
// this function is an alias to ChildrenFiltered() unless the selector is empty,
|
||||||
matches = appendWithoutDuplicates(matches, getChildren(n, true))
|
// in which case it is an alias to Contents().
|
||||||
|
func (this *Selection) ContentsFiltered(selector string) *Selection {
|
||||||
|
if selector != "" {
|
||||||
|
return this.ChildrenFiltered(selector)
|
||||||
}
|
}
|
||||||
return pushStack(this, matches)
|
return this.Contents()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Children() gets the child elements of each element in the Selection.
|
||||||
|
// It returns a new Selection object containing these elements.
|
||||||
|
func (this *Selection) Children() *Selection {
|
||||||
|
return pushStack(this, getSelectionChildren(this, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChildrenFiltered() gets the child elements of each element in the Selection,
|
||||||
|
// filtered by the specified selector. It returns a new
|
||||||
|
// Selection object containing these elements.
|
||||||
|
func (this *Selection) ChildrenFiltered(selector string) *Selection {
|
||||||
|
// Get the Children() unfiltered
|
||||||
|
nodes := getSelectionChildren(this, true)
|
||||||
|
// Create a temporary Selection to filter using winnow
|
||||||
|
sel := &Selection{nodes, this.document, nil}
|
||||||
|
// Filter based on selector
|
||||||
|
nodes = winnow(sel, selector, true)
|
||||||
|
// Push on the stack and return the "real" Selection
|
||||||
|
return pushStack(this, nodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the child nodes of each node in the Selection object, without
|
||||||
|
// duplicates.
|
||||||
|
func getSelectionChildren(s *Selection, elemOnly bool) (result []*html.Node) {
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
result = appendWithoutDuplicates(result, getChildren(n, elemOnly))
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the immediate children of the node, filtered on element nodes only
|
// Return the immediate children of the node, filtered on element nodes only
|
||||||
|
@@ -28,22 +28,6 @@ func TestFindInvalidSelector(t *testing.T) {
|
|||||||
Doc().Find(":+ ^")
|
Doc().Find(":+ ^")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEachEmptySelection(t *testing.T) {
|
|
||||||
var cnt int
|
|
||||||
|
|
||||||
sel := Doc().Find("zzzz")
|
|
||||||
sel.Each(func(i int, n *Selection) {
|
|
||||||
cnt++
|
|
||||||
})
|
|
||||||
if cnt > 0 {
|
|
||||||
t.Error("Expected Each() to not be called on empty Selection.")
|
|
||||||
}
|
|
||||||
sel2 := sel.Find("div")
|
|
||||||
if sel2.Nodes != nil {
|
|
||||||
t.Error("Expected Find() on empty Selection to return an empty Selection.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChainedFind(t *testing.T) {
|
func TestChainedFind(t *testing.T) {
|
||||||
sel := Doc().Find("div.hero-unit").Find(".row-fluid")
|
sel := Doc().Find("div.hero-unit").Find(".row-fluid")
|
||||||
if sel.Nodes == nil || len(sel.Nodes) != 4 {
|
if sel.Nodes == nil || len(sel.Nodes) != 4 {
|
||||||
@@ -53,6 +37,16 @@ func TestChainedFind(t *testing.T) {
|
|||||||
|
|
||||||
func TestChildren(t *testing.T) {
|
func TestChildren(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").Children()
|
sel := Doc().Find(".pvk-content").Children()
|
||||||
|
if len(sel.Nodes) != 5 {
|
||||||
|
t.Errorf("Expected 5 child nodes, got %v.", len(sel.Nodes))
|
||||||
|
for _, n := range sel.Nodes {
|
||||||
|
t.Logf("%+v", n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContents(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").Contents()
|
||||||
if len(sel.Nodes) != 13 {
|
if len(sel.Nodes) != 13 {
|
||||||
t.Errorf("Expected 13 child nodes, got %v.", len(sel.Nodes))
|
t.Errorf("Expected 13 child nodes, got %v.", len(sel.Nodes))
|
||||||
for _, n := range sel.Nodes {
|
for _, n := range sel.Nodes {
|
||||||
@@ -71,6 +65,16 @@ func TestChildrenFiltered(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContentsFiltered(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").ContentsFiltered(".hero-unit")
|
||||||
|
if len(sel.Nodes) != 1 {
|
||||||
|
t.Errorf("Expected 1 child nodes, got %v.", len(sel.Nodes))
|
||||||
|
for _, n := range sel.Nodes {
|
||||||
|
t.Logf("%+v", n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestChildrenFilteredNone(t *testing.T) {
|
func TestChildrenFilteredNone(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").ChildrenFiltered("a.btn")
|
sel := Doc().Find(".pvk-content").ChildrenFiltered("a.btn")
|
||||||
if len(sel.Nodes) != 0 {
|
if len(sel.Nodes) != 0 {
|
||||||
|
Reference in New Issue
Block a user