From 520f19d599ff1ee18c8b769c5d691597c97ee5b6 Mon Sep 17 00:00:00 2001 From: Martin Angers Date: Sun, 28 Jan 2018 14:41:06 -0500 Subject: [PATCH] add ToEnd marker to Slice until the end of the Selection --- array.go | 25 +++++++++++++++++++++++-- array_test.go | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/array.go b/array.go index d7af5ee..1b1f6cb 100644 --- a/array.go +++ b/array.go @@ -4,6 +4,16 @@ import ( "golang.org/x/net/html" ) +const ( + maxUint = ^uint(0) + maxInt = int(maxUint >> 1) + + // ToEnd is a special index value that can be used as end index in a call + // to Slice so that all elements are selected until the end of the Selection. + // It is equivalent to passing (*Selection).Length(). + ToEnd = maxInt +) + // First reduces the set of matched elements to the first in the set. // It returns a new Selection object, and an empty Selection object if the // the selection is empty. @@ -35,12 +45,23 @@ func (s *Selection) Eq(index int) *Selection { } // Slice reduces the set of matched elements to a subset specified by a range -// of indices. +// of indices. The start index is 0-based and indicates the index of the first +// element to select. The end index is 0-based and indicates the index at which +// the elements stop being selected (the end index is not selected). +// +// The indices may be negative, in which case they represent an offset from the +// end of the selection. +// +// The special value ToEnd may be specified as end index, in which case all elements +// until the end are selected. This works both for a positive and negative start +// index. func (s *Selection) Slice(start, end int) *Selection { if start < 0 { start += len(s.Nodes) } - if end < 0 { + if end == ToEnd { + end = len(s.Nodes) + } else if end < 0 { end += len(s.Nodes) } return pushStack(s, s.Nodes[start:end]) diff --git a/array_test.go b/array_test.go index 8e50f75..7857b38 100644 --- a/array_test.go +++ b/array_test.go @@ -98,6 +98,17 @@ func TestSlice(t *testing.T) { sel := Doc().Find(".pvk-content").Slice(0, 2) assertLength(t, sel.Nodes, 2) + assertSelectionIs(t, sel, "#pc1", "#pc2") +} + +func TestSliceToEnd(t *testing.T) { + sel := Doc().Find(".pvk-content").Slice(1, ToEnd) + + assertLength(t, sel.Nodes, 2) + assertSelectionIs(t, sel.Eq(0), "#pc2") + if _, ok := sel.Eq(1).Attr("id"); ok { + t.Error("Want no attribute ID, got one") + } } func TestSliceEmpty(t *testing.T) { @@ -110,6 +121,11 @@ func TestSliceInvalid(t *testing.T) { Doc().Find("").Slice(0, 2) } +func TestSliceInvalidToEnd(t *testing.T) { + defer assertPanic(t) + Doc().Find("").Slice(2, ToEnd) +} + func TestSliceOutOfBounds(t *testing.T) { defer assertPanic(t) Doc().Find(".pvk-content").Slice(2, 12) @@ -135,6 +151,12 @@ func TestNegativeSliceBoth(t *testing.T) { assertSelectionIs(t, sel.Eq(1), "#cf3") } +func TestNegativeSliceToEnd(t *testing.T) { + sel := Doc().Find(".container-fluid").Slice(-3, ToEnd) + assertLength(t, sel.Nodes, 3) + assertSelectionIs(t, sel, "#cf2", "#cf3", "#cf4") +} + func TestNegativeSliceOutOfBounds(t *testing.T) { defer assertPanic(t) Doc().Find(".container-fluid").Slice(-12, -7)