diff --git a/array.go b/array.go index 990ee27..baa00fb 100644 --- a/array.go +++ b/array.go @@ -41,3 +41,49 @@ func (this *Selection) Get(index int) *html.Node { } return this.Nodes[index] } + +// Index() returns the position of the first element within the Selection object relative to +// its sibling elements. +func (this *Selection) Index() int { + // TODO : Eventually refactor with prevAll(), like jQuery's code + if len(this.Nodes) > 0 { + n := this.Nodes[0] + if p := n.Parent; p != nil { + var i = 0 + for _, c := range p.Child { + if c == n { + // This is the index of the element + return i + } else if c.Type == html.ElementNode { + i++ + } + } + } + } + return -1 +} + +// IndexSelector() returns the position of the first element within the Selection object +// relative to the elements matched by the selector, or -1 if not found. +func (this *Selection) IndexSelector(selector string) int { + if len(this.Nodes) > 0 { + sel := this.document.Find(selector) + return indexInSlice(sel.Nodes, this.Nodes[0]) + } + return -1 +} + +// IndexOfNode() returns the position of the specified node within the Selection object, +// or -1 if not found. +func (this *Selection) IndexOfNode(node *html.Node) int { + return indexInSlice(this.Nodes, node) +} + +// IndexOfSelection() returns the position of the first node in the specified Selection object +// within this Selection object, or -1 if not found. +func (this *Selection) IndexOfSelection(s *Selection) int { + if len(s.Nodes) > 0 { + return indexInSlice(this.Nodes, s.Nodes[0]) + } + return -1 +} diff --git a/array_test.go b/array_test.go index 5ab8749..e1f7d42 100644 --- a/array_test.go +++ b/array_test.go @@ -93,3 +93,39 @@ func TestGetInvalid(t *testing.T) { sel := doc.Find(".pvk-content") sel.Get(129) } + +func TestIndex(t *testing.T) { + sel := doc.Find(".pvk-content") + if i := sel.Index(); i != 1 { + t.Errorf("Expected index of 1, got %v.", i) + } +} + +func TestIndexSelector(t *testing.T) { + sel := doc.Find(".hero-unit") + if i := sel.IndexSelector("div"); i != 4 { + t.Errorf("Expected index of 4, got %v.", i) + } +} + +func TestIndexOfNode(t *testing.T) { + sel := doc.Find("div.pvk-gutter") + if i := sel.IndexOfNode(sel.Nodes[1]); i != 1 { + t.Errorf("Expected index of 1, got %v.", i) + } +} + +func TestIndexOfNilNode(t *testing.T) { + sel := doc.Find("div.pvk-gutter") + if i := sel.IndexOfNode(nil); i != -1 { + t.Errorf("Expected index of -1, got %v.", i) + } +} + +func TestIndexOfSelection(t *testing.T) { + sel := doc.Find("div") + sel2 := doc.Find(".hero-unit") + if i := sel.IndexOfSelection(sel2); i != 4 { + t.Errorf("Expected index of 4, got %v.", i) + } +} diff --git a/utilities.go b/utilities.go index 3334aba..398e53e 100644 --- a/utilities.go +++ b/utilities.go @@ -47,12 +47,19 @@ func nodeContains(container *html.Node, contained *html.Node) bool { // Checks if the target node is in the slice of nodes. func isInSlice(slice []*html.Node, node *html.Node) bool { - for _, n := range slice { - if n == node { - return true + return indexInSlice(slice, node) > -1 +} + +// Returns the index of the target node in the slice, or -1. +func indexInSlice(slice []*html.Node, node *html.Node) int { + if node != nil { + for i, n := range slice { + if n == node { + return i + } } } - return false + return -1 } // Appends the new nodes to the target slice, making sure no duplicate is added.