Revising ScrollIntoView Action
- Rewrote ScrollIntoView to be consistent with other query actions
This commit is contained in:
parent
f85f3777fa
commit
bf1d5ecfbc
7
input.go
7
input.go
|
@ -2,6 +2,7 @@ package chromedp
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/knq/chromedp/cdp"
|
||||
|
@ -51,11 +52,15 @@ func MouseClickXY(x, y int64, opts ...MouseOption) Action {
|
|||
|
||||
// MouseClickNode dispatches a mouse left button click event at the center of a
|
||||
// specified node.
|
||||
//
|
||||
// Note that the window will be scrolled if the node is not within the window's
|
||||
// viewport.
|
||||
func MouseClickNode(n *cdp.Node, opts ...MouseOption) Action {
|
||||
return ActionFunc(func(ctxt context.Context, h cdp.Handler) error {
|
||||
var err error
|
||||
|
||||
err = ScrollIntoNode(n).Do(ctxt, h)
|
||||
var pos []int
|
||||
err = EvaluateAsDevTools(fmt.Sprintf(scrollIntoViewJS, n.FullXPath()), &pos).Do(ctxt, h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -10,6 +10,16 @@ import (
|
|||
"github.com/knq/chromedp/cdp/input"
|
||||
)
|
||||
|
||||
const (
|
||||
// inViewportJS is a javascript snippet that will get the specified node
|
||||
// position relative to the viewport and returns true if the specified node
|
||||
// is within the window's viewport.
|
||||
inViewportJS = `(function(a) {
|
||||
var r = a[0].getBoundingClientRect();
|
||||
return r.top >= 0 && r.left >= 0 && r.bottom <= window.innerHeight && r.right <= window.innerWidth;
|
||||
})($x('%s'))`
|
||||
)
|
||||
|
||||
func TestMouseClickXY(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@ -145,7 +155,7 @@ func TestMouseClickOffscreenNode(t *testing.T) {
|
|||
}
|
||||
|
||||
var ok bool
|
||||
err = c.Run(defaultContext, EvaluateAsDevTools(fmt.Sprintf(isOnViewJS, nodes[0].FullXPath()), &ok))
|
||||
err = c.Run(defaultContext, EvaluateAsDevTools(fmt.Sprintf(inViewportJS, nodes[0].FullXPath()), &ok))
|
||||
if err != nil {
|
||||
t.Fatalf("got error: %v", err)
|
||||
}
|
||||
|
|
25
nav.go
25
nav.go
|
@ -3,7 +3,6 @@ package chromedp
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/knq/chromedp/cdp"
|
||||
"github.com/knq/chromedp/cdp/page"
|
||||
|
@ -131,27 +130,3 @@ func Title(title *string) Action {
|
|||
|
||||
return EvaluateAsDevTools(`document.title`, title)
|
||||
}
|
||||
|
||||
// ScrollIntoNode scrolls the window to the specified node.
|
||||
func ScrollIntoNode(n *cdp.Node, opts ...QueryOption) Action {
|
||||
return ActionFunc(func(ctxt context.Context, h cdp.Handler) error {
|
||||
var res bool
|
||||
err := EvaluateAsDevTools(fmt.Sprintf(isOnViewJS, n.FullXPath()), &res).Do(ctxt, h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if res {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = EvaluateAsDevTools(fmt.Sprintf(scrollIntoViewJS, n.FullXPath()), &res).Do(ctxt, h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !res {
|
||||
return fmt.Errorf("could not scroll into node %d", n.NodeID)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
|
22
query.go
22
query.go
|
@ -492,3 +492,25 @@ func MatchedStyle(sel interface{}, style **css.GetMatchedStylesForNodeReturns, o
|
|||
return nil
|
||||
}, opts...)
|
||||
}
|
||||
|
||||
// ScrollIntoView scrolls the window to the first node matching the selector.
|
||||
func ScrollIntoView(sel interface{}, opts ...QueryOption) Action {
|
||||
return QueryAfter(sel, func(ctxt context.Context, h cdp.Handler, nodes ...*cdp.Node) error {
|
||||
if len(nodes) < 1 {
|
||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||
}
|
||||
|
||||
var err error
|
||||
var pos []int
|
||||
err = EvaluateAsDevTools(fmt.Sprintf(scrollIntoViewJS, nodes[0].FullXPath()), &pos).Do(ctxt, h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if pos == nil {
|
||||
return fmt.Errorf("could not scroll into node %d", nodes[0].NodeID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, opts...)
|
||||
}
|
||||
|
|
30
util.go
30
util.go
|
@ -30,7 +30,7 @@ const (
|
|||
}
|
||||
}
|
||||
return s;
|
||||
})($x("%s/node()"))`
|
||||
})($x('%s/node()'))`
|
||||
|
||||
// blurJS is a javscript snippet that blurs the specified element.
|
||||
blurJS = `(function(a) {
|
||||
|
@ -38,26 +38,6 @@ const (
|
|||
return true;
|
||||
})($x('%s'))`
|
||||
|
||||
// isOnViewJS is a javascript snippet that will get the specified node
|
||||
// position relative to the viewport and returns true or false depending
|
||||
// on if the specified node is on view port.
|
||||
isOnViewJS = `(function(a) {
|
||||
var rect = a[0].getBoundingClientRect();
|
||||
return (
|
||||
rect.top >= 0 &&
|
||||
rect.left >= 0 &&
|
||||
rect.bottom <= window.innerHeight &&
|
||||
rect.right <= window.innerWidth
|
||||
);
|
||||
})($x('%s'))`
|
||||
|
||||
// scrollIntoViewJS is a javascript snippet that scrolls the window to the
|
||||
// specified node.
|
||||
scrollIntoViewJS = `(function(a) {
|
||||
a[0].scrollIntoView(true);
|
||||
return true
|
||||
})($x('%s'))`
|
||||
|
||||
// scrollJS is a javascript snippet that scrolls the window to the
|
||||
// specified x, y coordinates and then returns the actual window x/y after
|
||||
// execution.
|
||||
|
@ -66,6 +46,14 @@ const (
|
|||
return [window.scrollX, window.scrollY];
|
||||
})(%d, %d)`
|
||||
|
||||
// scrollIntoViewJS is a javascript snippet that scrolls the specified node
|
||||
// into the window's viewport (if needed), returning the actual window x/y
|
||||
// after execution.
|
||||
scrollIntoViewJS = `(function(a) {
|
||||
a[0].scrollIntoViewIfNeeded(true);
|
||||
return [window.scrollX, window.scrollY];
|
||||
})($x('%s'))`
|
||||
|
||||
// submitJS is a javascript snippet that will call the containing form's
|
||||
// submit function, returning true or false if the call was successful.
|
||||
submitJS = `(function(a) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user