diff --git a/traversal.go b/traversal.go index 4ff5eff..75ae31b 100644 --- a/traversal.go +++ b/traversal.go @@ -2,7 +2,9 @@ package goquery import ( "code.google.com/p/cascadia" + "errors" "exp/html" + "fmt" ) type siblingType int @@ -272,7 +274,18 @@ func getSiblingNodes(nodes []*html.Node, st siblingType) []*html.Node { // Get the parent and loop through all children if p := n.Parent; p != nil { - return getChildrenWithSiblingType(p, st, n) + if st == siblingPrevAll || st == siblingPrevUntil { + // Find the index of this node + for i, c := range p.Child { + if c == n { + // Looking for previous nodes, so start at index - 1 upwards + return getChildrenWithSiblingType(p, st, n, i-1, -1) + } + } + panic(errors.New(fmt.Sprintf("Could not find node %+v in his parent's Child slice.", n))) + } else { + return getChildrenWithSiblingType(p, st, n, 0, 1) + } } return nil }) @@ -282,18 +295,23 @@ func getSiblingNodes(nodes []*html.Node, st siblingType) []*html.Node { // based on the sibling type request. func getChildrenNodes(nodes []*html.Node, st siblingType) []*html.Node { return mapNodes(nodes, func(i int, n *html.Node) []*html.Node { - return getChildrenWithSiblingType(n, st, nil) + return getChildrenWithSiblingType(n, st, nil, 0, 1) }) } // Gets the children of the specified parent, based on the requested sibling // type, skipping a specified node if required. -func getChildrenWithSiblingType(parent *html.Node, st siblingType, skipNode *html.Node) (result []*html.Node) { +func getChildrenWithSiblingType(parent *html.Node, st siblingType, skipNode *html.Node, + startIndex int, increment int) (result []*html.Node) { + var prev *html.Node var nFound bool + var end = len(parent.Child) - for _, c := range parent.Child { - // Care only about elements + for i := startIndex; i >= 0 && i < end; i += increment { + c := parent.Child[i] + + // Care only about elements unless we explicitly request all types of elements if c.Type == html.ElementNode || st == siblingAllIncludingNonElements { // Is it the existing node? if c == skipNode { diff --git a/traversal_test.go b/traversal_test.go index d7483eb..64ec748 100644 --- a/traversal_test.go +++ b/traversal_test.go @@ -112,6 +112,29 @@ func TestParents(t *testing.T) { AssertLength(t, sel.Nodes, 8) } +func TestParentsOrder(t *testing.T) { + sel := Doc().Root.Find("#cf2").Parents() + AssertLength(t, sel.Nodes, 6) + if !sel.Eq(0).HasClass("hero-unit") { + t.Errorf("Element at 0 should be hero-unit, found %+v.", sel.Get(0)) + } + if !sel.Eq(1).HasClass("pvk-content") { + t.Errorf("Element at 1 should be pvk-content, found %+v.", sel.Get(1)) + } + if !sel.Eq(2).Is("div.row-fluid") { + t.Errorf("Element at 2 should be row-fluid, found %+v.", sel.Get(2)) + } + if !sel.Eq(3).Is("#cf1") { + t.Errorf("Element at 3 should be cf1, found %+v.", sel.Get(3)) + } + if !sel.Eq(4).Is("body") { + t.Errorf("Element at 4 should be body, found %+v.", sel.Get(4)) + } + if !sel.Eq(5).Is("html") { + t.Errorf("Element at 5 should be html, found %+v.", sel.Get(5)) + } +} + func TestParentsRollback(t *testing.T) { sel := Doc().Root.Find(".container-fluid") sel2 := sel.Parents().End() @@ -351,6 +374,17 @@ func TestPrevAll(t *testing.T) { AssertLength(t, sel.Nodes, 2) } +func TestPrevAllOrder(t *testing.T) { + sel := Doc().Root.Find("[ng-view]").PrevAll() + AssertLength(t, sel.Nodes, 2) + if !sel.Eq(0).Is("#cf4") { + t.Errorf("Element at 0 should be cf4, found %+v.", sel.Get(0)) + } + if !sel.Eq(1).Is("#cf3") { + t.Errorf("Element at 1 should be cf3, found %+v.", sel.Get(1)) + } +} + func TestPrevAllRollback(t *testing.T) { sel := Doc().Root.Find("[ng-view]") sel2 := sel.PrevAll().End()