1package goquery
  2
  3import (
  4	"golang.org/x/net/html"
  5)
  6
  7const (
  8	maxUint = ^uint(0)
  9	maxInt  = int(maxUint >> 1)
 10
 11	// ToEnd is a special index value that can be used as end index in a call
 12	// to Slice so that all elements are selected until the end of the Selection.
 13	// It is equivalent to passing (*Selection).Length().
 14	ToEnd = maxInt
 15)
 16
 17// First reduces the set of matched elements to the first in the set.
 18// It returns a new Selection object, and an empty Selection object if the
 19// the selection is empty.
 20func (s *Selection) First() *Selection {
 21	return s.Eq(0)
 22}
 23
 24// Last reduces the set of matched elements to the last in the set.
 25// It returns a new Selection object, and an empty Selection object if
 26// the selection is empty.
 27func (s *Selection) Last() *Selection {
 28	return s.Eq(-1)
 29}
 30
 31// Eq reduces the set of matched elements to the one at the specified index.
 32// If a negative index is given, it counts backwards starting at the end of the
 33// set. It returns a new Selection object, and an empty Selection object if the
 34// index is invalid.
 35func (s *Selection) Eq(index int) *Selection {
 36	if index < 0 {
 37		index += len(s.Nodes)
 38	}
 39
 40	if index >= len(s.Nodes) || index < 0 {
 41		return newEmptySelection(s.document)
 42	}
 43
 44	return s.Slice(index, index+1)
 45}
 46
 47// Slice reduces the set of matched elements to a subset specified by a range
 48// of indices. The start index is 0-based and indicates the index of the first
 49// element to select. The end index is 0-based and indicates the index at which
 50// the elements stop being selected (the end index is not selected).
 51//
 52// The indices may be negative, in which case they represent an offset from the
 53// end of the selection.
 54//
 55// The special value ToEnd may be specified as end index, in which case all elements
 56// until the end are selected. This works both for a positive and negative start
 57// index.
 58func (s *Selection) Slice(start, end int) *Selection {
 59	if start < 0 {
 60		start += len(s.Nodes)
 61	}
 62	if end == ToEnd {
 63		end = len(s.Nodes)
 64	} else if end < 0 {
 65		end += len(s.Nodes)
 66	}
 67	return pushStack(s, s.Nodes[start:end])
 68}
 69
 70// Get retrieves the underlying node at the specified index.
 71// Get without parameter is not implemented, since the node array is available
 72// on the Selection object.
 73func (s *Selection) Get(index int) *html.Node {
 74	if index < 0 {
 75		index += len(s.Nodes) // Negative index gets from the end
 76	}
 77	return s.Nodes[index]
 78}
 79
 80// Index returns the position of the first element within the Selection object
 81// relative to its sibling elements.
 82func (s *Selection) Index() int {
 83	if len(s.Nodes) > 0 {
 84		return newSingleSelection(s.Nodes[0], s.document).PrevAll().Length()
 85	}
 86	return -1
 87}
 88
 89// IndexSelector returns the position of the first element within the
 90// Selection object relative to the elements matched by the selector, or -1 if
 91// not found.
 92func (s *Selection) IndexSelector(selector string) int {
 93	if len(s.Nodes) > 0 {
 94		sel := s.document.Find(selector)
 95		return indexInSlice(sel.Nodes, s.Nodes[0])
 96	}
 97	return -1
 98}
 99
100// IndexMatcher returns the position of the first element within the
101// Selection object relative to the elements matched by the matcher, or -1 if
102// not found.
103func (s *Selection) IndexMatcher(m Matcher) int {
104	if len(s.Nodes) > 0 {
105		sel := s.document.FindMatcher(m)
106		return indexInSlice(sel.Nodes, s.Nodes[0])
107	}
108	return -1
109}
110
111// IndexOfNode returns the position of the specified node within the Selection
112// object, or -1 if not found.
113func (s *Selection) IndexOfNode(node *html.Node) int {
114	return indexInSlice(s.Nodes, node)
115}
116
117// IndexOfSelection returns the position of the first node in the specified
118// Selection object within this Selection object, or -1 if not found.
119func (s *Selection) IndexOfSelection(sel *Selection) int {
120	if sel != nil && len(sel.Nodes) > 0 {
121		return indexInSlice(s.Nodes, sel.Nodes[0])
122	}
123	return -1
124}