1
0
mirror of https://github.com/MontFerret/ferret.git synced 2025-04-11 11:42:13 +02:00

Added scroll options (#471)

* Added scroll options

* Updated dependencies

* Updates after code review

* Updates after review

* Added comments
This commit is contained in:
Tim Voronov 2020-04-25 15:06:00 -04:00 committed by GitHub
parent 64fc010e6e
commit c9dfb79641
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 419 additions and 100 deletions

View File

@ -442,20 +442,20 @@ func (doc *HTMLDocument) WaitForStyleBySelectorAll(ctx context.Context, selector
return err return err
} }
func (doc *HTMLDocument) ScrollTop(ctx context.Context) error { func (doc *HTMLDocument) ScrollTop(ctx context.Context, options drivers.ScrollOptions) error {
return doc.input.ScrollTop(ctx) return doc.input.ScrollTop(ctx, options)
} }
func (doc *HTMLDocument) ScrollBottom(ctx context.Context) error { func (doc *HTMLDocument) ScrollBottom(ctx context.Context, options drivers.ScrollOptions) error {
return doc.input.ScrollBottom(ctx) return doc.input.ScrollBottom(ctx, options)
} }
func (doc *HTMLDocument) ScrollBySelector(ctx context.Context, selector values.String) error { func (doc *HTMLDocument) ScrollBySelector(ctx context.Context, selector values.String, options drivers.ScrollOptions) error {
return doc.input.ScrollIntoViewBySelector(ctx, selector.String()) return doc.input.ScrollIntoViewBySelector(ctx, selector.String(), options)
} }
func (doc *HTMLDocument) ScrollByXY(ctx context.Context, x, y values.Float) error { func (doc *HTMLDocument) ScrollByXY(ctx context.Context, x, y values.Float, options drivers.ScrollOptions) error {
return doc.input.ScrollByXY(ctx, float64(x), float64(y)) return doc.input.ScrollByXY(ctx, float64(x), float64(y), options)
} }
func (doc *HTMLDocument) logError(err error) *zerolog.Event { func (doc *HTMLDocument) logError(err error) *zerolog.Event {

View File

@ -1101,8 +1101,8 @@ func (el *HTMLElement) SelectBySelector(ctx context.Context, selector values.Str
return el.input.SelectBySelector(ctx, el.id.NodeID, selector.String(), value) return el.input.SelectBySelector(ctx, el.id.NodeID, selector.String(), value)
} }
func (el *HTMLElement) ScrollIntoView(ctx context.Context) error { func (el *HTMLElement) ScrollIntoView(ctx context.Context, options drivers.ScrollOptions) error {
return el.input.ScrollIntoView(ctx, el.id.ObjectID) return el.input.ScrollIntoView(ctx, el.id.ObjectID, options)
} }
func (el *HTMLElement) Focus(ctx context.Context) error { func (el *HTMLElement) Focus(ctx context.Context) error {

View File

@ -52,37 +52,41 @@ func (m *Manager) Mouse() *Mouse {
return m.mouse return m.mouse
} }
func (m *Manager) ScrollTop(ctx context.Context) error { func (m *Manager) ScrollTop(ctx context.Context, options drivers.ScrollOptions) error {
return m.exec.Eval(ctx, templates.ScrollTop()) return m.exec.Eval(ctx, templates.ScrollTop(options))
} }
func (m *Manager) ScrollBottom(ctx context.Context) error { func (m *Manager) ScrollBottom(ctx context.Context, options drivers.ScrollOptions) error {
return m.exec.Eval(ctx, templates.ScrollBottom()) return m.exec.Eval(ctx, templates.ScrollBottom(options))
} }
func (m *Manager) ScrollIntoView(ctx context.Context, objectID runtime.RemoteObjectID) error { func (m *Manager) ScrollIntoView(ctx context.Context, objectID runtime.RemoteObjectID, options drivers.ScrollOptions) error {
return m.exec.EvalWithArguments( return m.exec.EvalWithArguments(
ctx, ctx,
templates.ScrollIntoView(), templates.ScrollIntoView(options),
runtime.CallArgument{ runtime.CallArgument{
ObjectID: &objectID, ObjectID: &objectID,
}, },
) )
} }
func (m *Manager) ScrollIntoViewBySelector(ctx context.Context, selector string) error { func (m *Manager) ScrollIntoViewBySelector(ctx context.Context, selector string, options drivers.ScrollOptions) error {
return m.exec.Eval(ctx, templates.ScrollIntoViewBySelector(selector)) return m.exec.Eval(ctx, templates.ScrollIntoViewBySelector(selector, options))
} }
func (m *Manager) ScrollByXY(ctx context.Context, x, y float64) error { func (m *Manager) ScrollByXY(ctx context.Context, x, y float64, options drivers.ScrollOptions) error {
return m.exec.Eval( return m.exec.Eval(
ctx, ctx,
templates.Scroll(eval.ParamFloat(x), eval.ParamFloat(y)), templates.Scroll(eval.ParamFloat(x), eval.ParamFloat(y), options),
) )
} }
func (m *Manager) Focus(ctx context.Context, objectID runtime.RemoteObjectID) error { func (m *Manager) Focus(ctx context.Context, objectID runtime.RemoteObjectID) error {
err := m.ScrollIntoView(ctx, objectID) err := m.ScrollIntoView(ctx, objectID, drivers.ScrollOptions{
Behavior: drivers.ScrollBehaviorAuto,
Block: drivers.ScrollVerticalAlignmentCenter,
Inline: drivers.ScrollHorizontalAlignmentCenter,
})
if err != nil { if err != nil {
return err return err
@ -92,7 +96,11 @@ func (m *Manager) Focus(ctx context.Context, objectID runtime.RemoteObjectID) er
} }
func (m *Manager) FocusBySelector(ctx context.Context, parentNodeID dom.NodeID, selector string) error { func (m *Manager) FocusBySelector(ctx context.Context, parentNodeID dom.NodeID, selector string) error {
err := m.ScrollIntoViewBySelector(ctx, selector) err := m.ScrollIntoViewBySelector(ctx, selector, drivers.ScrollOptions{
Behavior: drivers.ScrollBehaviorAuto,
Block: drivers.ScrollVerticalAlignmentCenter,
Inline: drivers.ScrollHorizontalAlignmentCenter,
})
if err != nil { if err != nil {
return err return err
@ -120,7 +128,7 @@ func (m *Manager) BlurBySelector(ctx context.Context, parentObjectID runtime.Rem
} }
func (m *Manager) MoveMouse(ctx context.Context, objectID runtime.RemoteObjectID) error { func (m *Manager) MoveMouse(ctx context.Context, objectID runtime.RemoteObjectID) error {
if err := m.ScrollIntoView(ctx, objectID); err != nil { if err := m.ScrollIntoView(ctx, objectID, drivers.ScrollOptions{}); err != nil {
return err return err
} }
@ -134,7 +142,7 @@ func (m *Manager) MoveMouse(ctx context.Context, objectID runtime.RemoteObjectID
} }
func (m *Manager) MoveMouseBySelector(ctx context.Context, parentNodeID dom.NodeID, selector string) error { func (m *Manager) MoveMouseBySelector(ctx context.Context, parentNodeID dom.NodeID, selector string) error {
if err := m.ScrollIntoViewBySelector(ctx, selector); err != nil { if err := m.ScrollIntoViewBySelector(ctx, selector, drivers.ScrollOptions{}); err != nil {
return err return err
} }
@ -154,7 +162,7 @@ func (m *Manager) MoveMouseBySelector(ctx context.Context, parentNodeID dom.Node
} }
func (m *Manager) MoveMouseByXY(ctx context.Context, x, y float64) error { func (m *Manager) MoveMouseByXY(ctx context.Context, x, y float64) error {
if err := m.ScrollByXY(ctx, x, y); err != nil { if err := m.ScrollByXY(ctx, x, y, drivers.ScrollOptions{}); err != nil {
return err return err
} }
@ -162,7 +170,11 @@ func (m *Manager) MoveMouseByXY(ctx context.Context, x, y float64) error {
} }
func (m *Manager) Click(ctx context.Context, objectID runtime.RemoteObjectID, count int) error { func (m *Manager) Click(ctx context.Context, objectID runtime.RemoteObjectID, count int) error {
if err := m.ScrollIntoView(ctx, objectID); err != nil { if err := m.ScrollIntoView(ctx, objectID, drivers.ScrollOptions{
Behavior: drivers.ScrollBehaviorAuto,
Block: drivers.ScrollVerticalAlignmentCenter,
Inline: drivers.ScrollHorizontalAlignmentCenter,
}); err != nil {
return err return err
} }
@ -182,7 +194,11 @@ func (m *Manager) Click(ctx context.Context, objectID runtime.RemoteObjectID, co
} }
func (m *Manager) ClickBySelector(ctx context.Context, parentNodeID dom.NodeID, selector string, count int) error { func (m *Manager) ClickBySelector(ctx context.Context, parentNodeID dom.NodeID, selector string, count int) error {
if err := m.ScrollIntoViewBySelector(ctx, selector); err != nil { if err := m.ScrollIntoViewBySelector(ctx, selector, drivers.ScrollOptions{
Behavior: drivers.ScrollBehaviorAuto,
Block: drivers.ScrollVerticalAlignmentCenter,
Inline: drivers.ScrollHorizontalAlignmentCenter,
}); err != nil {
return err return err
} }
@ -208,7 +224,11 @@ func (m *Manager) ClickBySelector(ctx context.Context, parentNodeID dom.NodeID,
} }
func (m *Manager) ClickBySelectorAll(ctx context.Context, parentNodeID dom.NodeID, selector string, count int) error { func (m *Manager) ClickBySelectorAll(ctx context.Context, parentNodeID dom.NodeID, selector string, count int) error {
if err := m.ScrollIntoViewBySelector(ctx, selector); err != nil { if err := m.ScrollIntoViewBySelector(ctx, selector, drivers.ScrollOptions{
Behavior: drivers.ScrollBehaviorAuto,
Block: drivers.ScrollVerticalAlignmentCenter,
Inline: drivers.ScrollHorizontalAlignmentCenter,
}); err != nil {
return err return err
} }
@ -240,7 +260,11 @@ func (m *Manager) ClickBySelectorAll(ctx context.Context, parentNodeID dom.NodeI
} }
func (m *Manager) Type(ctx context.Context, objectID runtime.RemoteObjectID, params TypeParams) error { func (m *Manager) Type(ctx context.Context, objectID runtime.RemoteObjectID, params TypeParams) error {
err := m.ScrollIntoView(ctx, objectID) err := m.ScrollIntoView(ctx, objectID, drivers.ScrollOptions{
Behavior: drivers.ScrollBehaviorAuto,
Block: drivers.ScrollVerticalAlignmentCenter,
Inline: drivers.ScrollHorizontalAlignmentCenter,
})
if err != nil { if err != nil {
return err return err
@ -273,7 +297,11 @@ func (m *Manager) Type(ctx context.Context, objectID runtime.RemoteObjectID, par
} }
func (m *Manager) TypeBySelector(ctx context.Context, parentNodeID dom.NodeID, selector string, params TypeParams) error { func (m *Manager) TypeBySelector(ctx context.Context, parentNodeID dom.NodeID, selector string, params TypeParams) error {
err := m.ScrollIntoViewBySelector(ctx, selector) err := m.ScrollIntoViewBySelector(ctx, selector, drivers.ScrollOptions{
Behavior: drivers.ScrollBehaviorAuto,
Block: drivers.ScrollVerticalAlignmentCenter,
Inline: drivers.ScrollHorizontalAlignmentCenter,
})
if err != nil { if err != nil {
return err return err
@ -312,7 +340,11 @@ func (m *Manager) TypeBySelector(ctx context.Context, parentNodeID dom.NodeID, s
} }
func (m *Manager) Clear(ctx context.Context, objectID runtime.RemoteObjectID) error { func (m *Manager) Clear(ctx context.Context, objectID runtime.RemoteObjectID) error {
err := m.ScrollIntoView(ctx, objectID) err := m.ScrollIntoView(ctx, objectID, drivers.ScrollOptions{
Behavior: drivers.ScrollBehaviorAuto,
Block: drivers.ScrollVerticalAlignmentCenter,
Inline: drivers.ScrollHorizontalAlignmentCenter,
})
if err != nil { if err != nil {
return err return err
@ -334,7 +366,11 @@ func (m *Manager) Clear(ctx context.Context, objectID runtime.RemoteObjectID) er
} }
func (m *Manager) ClearBySelector(ctx context.Context, parentNodeID dom.NodeID, selector string) error { func (m *Manager) ClearBySelector(ctx context.Context, parentNodeID dom.NodeID, selector string) error {
err := m.ScrollIntoViewBySelector(ctx, selector) err := m.ScrollIntoViewBySelector(ctx, selector, drivers.ScrollOptions{
Behavior: drivers.ScrollBehaviorAuto,
Block: drivers.ScrollVerticalAlignmentCenter,
Inline: drivers.ScrollHorizontalAlignmentCenter,
})
if err != nil { if err != nil {
return err return err

View File

@ -19,11 +19,23 @@ const (
}; };
` `
scrollTemplate = `
window.scrollTo({
left: %s,
top: %s,
behavior: %s,
block: %s,
inline: %s
});
`
scrollTopTemplate = ` scrollTopTemplate = `
window.scrollTo({ window.scrollTo({
left: 0, left: 0,
top: 0, top: 0,
behavior: 'instant' behavior: %s,
block: %s,
inline: %s
}); });
` `
@ -31,7 +43,9 @@ const (
window.scrollTo({ window.scrollTo({
left: 0, left: 0,
top: window.document.body.scrollHeight, top: window.document.body.scrollHeight,
behavior: 'instant' behavior: %s,
block: %s,
inline: %s
}); });
` `
@ -42,53 +56,82 @@ const (
if (!isInViewport(el)) { if (!isInViewport(el)) {
el.scrollIntoView({ el.scrollIntoView({
block: 'center', behavior: %s,
inline: 'center', block: %s,
behavior: 'instant' inline: %s
}); });
} }
return true; return true;
} }
` `
)
func Scroll(x, y string) string { scrollIntoViewBySelectorTemplate = `
return fmt.Sprintf(`
window.scrollBy(%s, %s);
`, x, y)
}
func ScrollTop() string {
return scrollTopTemplate
}
func ScrollBottom() string {
return scrollBottomTemplate
}
func ScrollIntoView() string {
return scrollIntoViewTemplate
}
func ScrollIntoViewBySelector(selector string) string {
return fmt.Sprintf(`
const el = document.querySelector('%s'); const el = document.querySelector('%s');
if (el == null) { if (el == null) {
throw new Error('%s'); throw new Error('%s');
} }
%s ` + isElementInViewportTemplate + `
if (!isInViewport(el)) { if (!isInViewport(el)) {
el.scrollIntoView({ el.scrollIntoView({
block: 'center', behavior: %s,
inline: 'center', block: %s,
behavior: 'instant' inline: %s
}); });
} }
return true; return true;
`, selector, drivers.ErrNotFound, isElementInViewportTemplate) `
)
func Scroll(x, y string, options drivers.ScrollOptions) string {
return fmt.Sprintf(
scrollTemplate,
x,
y,
options.Behavior,
options.Block,
options.Inline,
)
}
func ScrollTop(options drivers.ScrollOptions) string {
return fmt.Sprintf(
scrollTopTemplate,
options.Behavior,
options.Block,
options.Inline,
)
}
func ScrollBottom(options drivers.ScrollOptions) string {
return fmt.Sprintf(
scrollBottomTemplate,
options.Behavior,
options.Block,
options.Inline,
)
}
func ScrollIntoView(options drivers.ScrollOptions) string {
return fmt.Sprintf(
scrollIntoViewTemplate,
options.Behavior,
options.Block,
options.Inline,
)
}
func ScrollIntoViewBySelector(selector string, options drivers.ScrollOptions) string {
return fmt.Sprintf(
scrollIntoViewBySelectorTemplate,
selector,
drivers.ErrNotFound,
options.Behavior,
options.Block,
options.Inline,
)
} }

View File

@ -207,19 +207,19 @@ func (doc *HTMLDocument) GetParentDocument(_ context.Context) (drivers.HTMLDocum
return doc.parent, nil return doc.parent, nil
} }
func (doc *HTMLDocument) ScrollTop(_ context.Context) error { func (doc *HTMLDocument) ScrollTop(_ context.Context, _ drivers.ScrollOptions) error {
return core.ErrNotSupported return core.ErrNotSupported
} }
func (doc *HTMLDocument) ScrollBottom(_ context.Context) error { func (doc *HTMLDocument) ScrollBottom(_ context.Context, _ drivers.ScrollOptions) error {
return core.ErrNotSupported return core.ErrNotSupported
} }
func (doc *HTMLDocument) ScrollBySelector(_ context.Context, _ values.String) error { func (doc *HTMLDocument) ScrollBySelector(_ context.Context, _ values.String, _ drivers.ScrollOptions) error {
return core.ErrNotSupported return core.ErrNotSupported
} }
func (doc *HTMLDocument) ScrollByXY(_ context.Context, _, _ values.Float) error { func (doc *HTMLDocument) ScrollByXY(_ context.Context, _, _ values.Float, _ drivers.ScrollOptions) error {
return core.ErrNotSupported return core.ErrNotSupported
} }

View File

@ -525,7 +525,7 @@ func (el *HTMLElement) SelectBySelector(_ context.Context, _ values.String, _ *v
return nil, core.ErrNotSupported return nil, core.ErrNotSupported
} }
func (el *HTMLElement) ScrollIntoView(_ context.Context) error { func (el *HTMLElement) ScrollIntoView(_ context.Context, _ drivers.ScrollOptions) error {
return core.ErrNotSupported return core.ErrNotSupported
} }

127
pkg/drivers/scroll.go Normal file
View File

@ -0,0 +1,127 @@
package drivers
import "strings"
// ScrollBehavior defines the transition animation.
// In HTML specification, default value is auto, but in Ferret it's instant.
// More details here https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
type ScrollBehavior int
const (
ScrollBehaviorInstant ScrollBehavior = 0
ScrollBehaviorSmooth ScrollBehavior = 1
ScrollBehaviorAuto ScrollBehavior = 2
)
func NewScrollBehavior(value string) ScrollBehavior {
switch strings.ToLower(value) {
case "instant":
return ScrollBehaviorInstant
case "smooth":
return ScrollBehaviorSmooth
default:
return ScrollBehaviorAuto
}
}
func (b ScrollBehavior) String() string {
switch b {
case ScrollBehaviorInstant:
return "instant"
case ScrollBehaviorSmooth:
return "smooth"
default:
return "auto"
}
}
// ScrollVerticalAlignment defines vertical alignment after scrolling.
// In HTML specification, default value is start, but in Ferret it's center.
// More details here https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
type ScrollVerticalAlignment int
const (
ScrollVerticalAlignmentCenter ScrollVerticalAlignment = 0
ScrollVerticalAlignmentStart ScrollVerticalAlignment = 1
ScrollVerticalAlignmentEnd ScrollVerticalAlignment = 2
ScrollVerticalAlignmentNearest ScrollVerticalAlignment = 3
)
func NewScrollVerticalAlignment(value string) ScrollVerticalAlignment {
switch strings.ToLower(value) {
case "center":
return ScrollVerticalAlignmentCenter
case "start":
return ScrollVerticalAlignmentStart
case "end":
return ScrollVerticalAlignmentEnd
case "nearest":
return ScrollVerticalAlignmentNearest
default:
return ScrollVerticalAlignmentCenter
}
}
func (a ScrollVerticalAlignment) String() string {
switch a {
case ScrollVerticalAlignmentCenter:
return "center"
case ScrollVerticalAlignmentStart:
return "start"
case ScrollVerticalAlignmentEnd:
return "end"
case ScrollVerticalAlignmentNearest:
return "nearest"
default:
return "center"
}
}
// ScrollHorizontalAlignment defines horizontal alignment after scrolling.
// In HTML specification, default value is nearest, but in Ferret it's center.
// More details here https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
type ScrollHorizontalAlignment int
const (
ScrollHorizontalAlignmentCenter ScrollHorizontalAlignment = 0
ScrollHorizontalAlignmentStart ScrollHorizontalAlignment = 1
ScrollHorizontalAlignmentEnd ScrollHorizontalAlignment = 2
ScrollHorizontalAlignmentNearest ScrollHorizontalAlignment = 3
)
func NewScrollHorizontalAlignment(value string) ScrollHorizontalAlignment {
switch strings.ToLower(value) {
case "center":
return ScrollHorizontalAlignmentCenter
case "start":
return ScrollHorizontalAlignmentStart
case "end":
return ScrollHorizontalAlignmentEnd
case "nearest":
return ScrollHorizontalAlignmentNearest
default:
return ScrollHorizontalAlignmentCenter
}
}
func (a ScrollHorizontalAlignment) String() string {
switch a {
case ScrollHorizontalAlignmentCenter:
return "center"
case ScrollHorizontalAlignmentNearest:
return "nearest"
case ScrollHorizontalAlignmentStart:
return "start"
case ScrollHorizontalAlignmentEnd:
return "end"
default:
return "center"
}
}
// ScrollOptions defines how scroll animation should be performed.
type ScrollOptions struct {
Behavior ScrollBehavior
Block ScrollVerticalAlignment
Inline ScrollHorizontalAlignment
}

View File

@ -111,7 +111,7 @@ type (
SelectBySelector(ctx context.Context, selector values.String, value *values.Array) (*values.Array, error) SelectBySelector(ctx context.Context, selector values.String, value *values.Array) (*values.Array, error)
ScrollIntoView(ctx context.Context) error ScrollIntoView(ctx context.Context, options ScrollOptions) error
Focus(ctx context.Context) error Focus(ctx context.Context) error
@ -147,13 +147,13 @@ type (
GetChildDocuments(ctx context.Context) (*values.Array, error) GetChildDocuments(ctx context.Context) (*values.Array, error)
ScrollTop(ctx context.Context) error ScrollTop(ctx context.Context, options ScrollOptions) error
ScrollBottom(ctx context.Context) error ScrollBottom(ctx context.Context, options ScrollOptions) error
ScrollBySelector(ctx context.Context, selector values.String) error ScrollBySelector(ctx context.Context, selector values.String, options ScrollOptions) error
ScrollByXY(ctx context.Context, x, y values.Float) error ScrollByXY(ctx context.Context, x, y values.Float, options ScrollOptions) error
MoveMouseByXY(ctx context.Context, x, y values.Float) error MoveMouseByXY(ctx context.Context, x, y values.Float) error

View File

@ -105,3 +105,35 @@ func waitTimeout(ctx context.Context, value values.Int) (context.Context, contex
time.Duration(value)*time.Millisecond, time.Duration(value)*time.Millisecond,
) )
} }
func toScrollOptions(value core.Value) (drivers.ScrollOptions, error) {
result := drivers.ScrollOptions{}
err := core.ValidateType(value, types.Object)
if err != nil {
return result, err
}
obj := value.(*values.Object)
behavior, exists := obj.Get("behavior")
if exists {
result.Behavior = drivers.NewScrollBehavior(behavior.String())
}
block, exists := obj.Get("block")
if exists {
result.Block = drivers.NewScrollVerticalAlignment(block.String())
}
inline, exists := obj.Get("inline")
if exists {
result.Inline = drivers.NewScrollHorizontalAlignment(inline.String())
}
return result, nil
}

View File

@ -10,8 +10,9 @@ import (
// SCROLL_BOTTOM scrolls the document's window to its bottom. // SCROLL_BOTTOM scrolls the document's window to its bottom.
// @param doc (HTMLDocument) - Target document. // @param doc (HTMLDocument) - Target document.
// @param options (ScrollOptions) - Scroll options. Optional.
func ScrollBottom(ctx context.Context, args ...core.Value) (core.Value, error) { func ScrollBottom(ctx context.Context, args ...core.Value) (core.Value, error) {
err := core.ValidateArgs(args, 1, 1) err := core.ValidateArgs(args, 1, 2)
if err != nil { if err != nil {
return values.None, err return values.None, err
@ -23,5 +24,15 @@ func ScrollBottom(ctx context.Context, args ...core.Value) (core.Value, error) {
return values.None, err return values.None, err
} }
return values.None, doc.ScrollBottom(ctx) var opts drivers.ScrollOptions
if len(args) > 1 {
opts, err = toScrollOptions(args[1])
if err != nil {
return values.None, err
}
}
return values.None, doc.ScrollBottom(ctx, opts)
} }

View File

@ -3,6 +3,8 @@ package html
import ( import (
"context" "context"
"github.com/pkg/errors"
"github.com/MontFerret/ferret/pkg/drivers" "github.com/MontFerret/ferret/pkg/drivers"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
@ -11,44 +13,90 @@ import (
// SCROLL_ELEMENT scrolls an element on. // SCROLL_ELEMENT scrolls an element on.
// @param docOrEl (HTMLDocument|HTMLElement) - Target document or element. // @param docOrEl (HTMLDocument|HTMLElement) - Target document or element.
// @param selector (String, options) - If document is passed, this param must represent an element selector. // @param selector (String) - If document is passed, this param must represent an element selector.
// @param options (ScrollOptions) - Scroll options. Optional.
func ScrollInto(ctx context.Context, args ...core.Value) (core.Value, error) { func ScrollInto(ctx context.Context, args ...core.Value) (core.Value, error) {
err := core.ValidateArgs(args, 1, 2) err := core.ValidateArgs(args, 1, 3)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }
if len(args) == 2 { var doc drivers.HTMLDocument
doc, err := drivers.ToDocument(args[0]) var el drivers.HTMLElement
var selector values.String
var opts drivers.ScrollOptions
if len(args) == 3 {
if err = core.ValidateType(args[1], types.String); err != nil {
return values.None, errors.Wrap(err, "selector")
}
if err = core.ValidateType(args[2], types.Object); err != nil {
return values.None, errors.Wrap(err, "options")
}
doc, err = drivers.ToDocument(args[0])
if err != nil { if err != nil {
return values.None, errors.Wrap(err, "document")
}
selector = values.ToString(args[1])
o, err := toScrollOptions(args[2])
if err != nil {
return values.None, errors.Wrap(err, "options")
}
opts = o
} else if len(args) == 2 {
if err = core.ValidateType(args[1], types.String, types.Object); err != nil {
return values.None, err return values.None, err
} }
err = core.ValidateType(args[1], types.String) if args[1].Type() == types.String {
doc, err = drivers.ToDocument(args[0])
if err != nil {
return values.None, errors.Wrap(err, "document")
}
selector = values.ToString(args[1])
} else {
el, err = drivers.ToElement(args[0])
o, err := toScrollOptions(args[1])
if err != nil {
return values.None, errors.Wrap(err, "options")
}
opts = o
}
} else {
el, err = drivers.ToElement(args[0])
if err != nil { if err != nil {
return values.None, err return values.None, errors.Wrap(err, "element")
}
}
if doc != nil {
if selector != values.EmptyString {
return values.None, doc.ScrollBySelector(ctx, selector, opts)
} }
selector := args[1].(values.String) return values.None, doc.GetElement().ScrollIntoView(ctx, opts)
return values.None, doc.ScrollBySelector(ctx, selector)
} }
err = core.ValidateType(args[0], drivers.HTMLElementType) if el != nil {
return values.None, el.ScrollIntoView(ctx, opts)
if err != nil {
return values.None, err
} }
// GetElement return values.None, core.TypeError(
el, err := drivers.ToElement(args[0]) args[0].Type(),
drivers.HTMLPageType,
if err != nil { drivers.HTMLDocumentType,
return values.None, err drivers.HTMLElementType,
} )
return values.None, el.ScrollIntoView(ctx)
} }

View File

@ -10,8 +10,9 @@ import (
// SCROLL_TOP scrolls the document's window to its top. // SCROLL_TOP scrolls the document's window to its top.
// @param doc (HTMLDocument) - Target document. // @param doc (HTMLDocument) - Target document.
// @param options (ScrollOptions) - Scroll options. Optional.
func ScrollTop(ctx context.Context, args ...core.Value) (core.Value, error) { func ScrollTop(ctx context.Context, args ...core.Value) (core.Value, error) {
err := core.ValidateArgs(args, 1, 1) err := core.ValidateArgs(args, 1, 2)
if err != nil { if err != nil {
return values.None, err return values.None, err
@ -23,5 +24,15 @@ func ScrollTop(ctx context.Context, args ...core.Value) (core.Value, error) {
return values.None, err return values.None, err
} }
return values.None, doc.ScrollTop(ctx) var opts drivers.ScrollOptions
if len(args) > 1 {
opts, err = toScrollOptions(args[1])
if err != nil {
return values.None, err
}
}
return values.None, doc.ScrollTop(ctx, opts)
} }

View File

@ -13,8 +13,9 @@ import (
// @param doc (HTMLDocument) - HTML document. // @param doc (HTMLDocument) - HTML document.
// @param x (Int|Float) - X coordinate. // @param x (Int|Float) - X coordinate.
// @param y (Int|Float) - Y coordinate. // @param y (Int|Float) - Y coordinate.
// @param options (ScrollOptions) - Scroll options. Optional.
func ScrollXY(ctx context.Context, args ...core.Value) (core.Value, error) { func ScrollXY(ctx context.Context, args ...core.Value) (core.Value, error) {
err := core.ValidateArgs(args, 3, 3) err := core.ValidateArgs(args, 3, 4)
if err != nil { if err != nil {
return values.None, err return values.None, err
@ -41,5 +42,15 @@ func ScrollXY(ctx context.Context, args ...core.Value) (core.Value, error) {
x := values.ToFloat(args[1]) x := values.ToFloat(args[1])
y := values.ToFloat(args[2]) y := values.ToFloat(args[2])
return values.None, doc.ScrollByXY(ctx, x, y) var opts drivers.ScrollOptions
if len(args) > 3 {
opts, err = toScrollOptions(args[3])
if err != nil {
return values.None, err
}
}
return values.None, doc.ScrollByXY(ctx, x, y, opts)
} }