chromedp/input.go

199 lines
5.2 KiB
Go
Raw Normal View History

2017-01-24 15:09:23 +00:00
package chromedp
import (
"context"
"fmt"
2017-01-24 15:09:23 +00:00
"time"
2017-01-26 07:28:34 +00:00
"github.com/knq/chromedp/cdp"
2017-01-24 15:09:23 +00:00
"github.com/knq/chromedp/cdp/dom"
"github.com/knq/chromedp/cdp/input"
"github.com/knq/chromedp/kb"
2017-01-24 15:09:23 +00:00
)
// MouseAction is a mouse action.
func MouseAction(typ input.MouseType, x, y int64, opts ...MouseOption) Action {
2017-07-13 00:46:32 +00:00
me := input.DispatchMouseEvent(typ, float64(x), float64(y))
2017-02-08 14:35:12 +00:00
// apply opts
2017-01-24 15:09:23 +00:00
for _, o := range opts {
2017-02-08 14:35:12 +00:00
me = o(me)
2017-01-24 15:09:23 +00:00
}
2017-02-08 14:35:12 +00:00
return me
2017-01-24 15:09:23 +00:00
}
2017-02-08 14:35:12 +00:00
// MouseClickXY sends a left mouse button click (ie, mousePressed and
// mouseReleased event) at the X, Y location.
2017-01-24 15:09:23 +00:00
func MouseClickXY(x, y int64, opts ...MouseOption) Action {
return ActionFunc(func(ctxt context.Context, h cdp.Handler) error {
2017-02-08 14:35:12 +00:00
me := &input.DispatchMouseEventParams{
Type: input.MousePressed,
2017-07-13 00:46:32 +00:00
X: float64(x),
Y: float64(y),
2017-02-08 14:35:12 +00:00
Button: input.ButtonLeft,
ClickCount: 1,
}
// apply opts
for _, o := range opts {
me = o(me)
}
err := me.Do(ctxt, h)
if err != nil {
return err
}
me.Type = input.MouseReleased
return me.Do(ctxt, h)
})
2017-01-24 15:09:23 +00:00
}
// 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 {
2017-02-08 14:35:12 +00:00
var err error
var pos []int
err = EvaluateAsDevTools(fmt.Sprintf(scrollIntoViewJS, n.FullXPath()), &pos).Do(ctxt, h)
2017-02-08 14:35:12 +00:00
if err != nil {
return err
}
2017-02-08 14:35:12 +00:00
2017-01-24 15:09:23 +00:00
box, err := dom.GetBoxModel(n.NodeID).Do(ctxt, h)
if err != nil {
return err
}
c := len(box.Content)
2017-02-08 14:35:12 +00:00
if c%2 != 0 || c < 1 {
2017-01-24 15:09:23 +00:00
return ErrInvalidDimensions
}
var x, y int64
for i := 0; i < c; i += 2 {
x += int64(box.Content[i])
y += int64(box.Content[i+1])
}
2017-02-08 14:35:12 +00:00
x /= int64(c / 2)
y /= int64(c / 2)
2017-01-24 15:09:23 +00:00
2017-02-08 14:35:12 +00:00
return MouseClickXY(x, y, opts...).Do(ctxt, h)
2017-01-24 15:09:23 +00:00
})
}
// MouseOption is a mouse action option.
type MouseOption func(*input.DispatchMouseEventParams) *input.DispatchMouseEventParams
2017-02-08 14:35:12 +00:00
// Button is a mouse action option to set the button to click from a string.
func Button(btn string) MouseOption {
return ButtonType(input.ButtonType(btn))
}
// ButtonType is a mouse action option to set the button to click.
func ButtonType(button input.ButtonType) MouseOption {
2017-01-24 15:09:23 +00:00
return func(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
return p.WithButton(button)
}
}
2017-02-08 14:35:12 +00:00
// ButtonLeft is a mouse action option to set the button clicked as the left
// mouse button.
func ButtonLeft(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
return p.WithButton(input.ButtonLeft)
}
// ButtonMiddle is a mouse action option to set the button clicked as the middle
// mouse button.
func ButtonMiddle(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
return p.WithButton(input.ButtonMiddle)
}
// ButtonRight is a mouse action option to set the button clicked as the right
// mouse button.
func ButtonRight(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
return p.WithButton(input.ButtonRight)
}
// ButtonNone is a mouse action option to set the button clicked as none (used
// for mouse movements).
func ButtonNone(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
return p.WithButton(input.ButtonNone)
2017-01-24 15:09:23 +00:00
}
2017-02-08 14:35:12 +00:00
// ButtonModifiers is a mouse action option to add additional input modifiers
// for a button click.
2017-01-24 15:09:23 +00:00
func ButtonModifiers(modifiers ...input.Modifier) MouseOption {
return func(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
for _, m := range modifiers {
p.Modifiers |= m
}
return p
}
}
// ClickCount is a mouse action option to set the click count.
func ClickCount(n int) MouseOption {
return func(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
return p.WithClickCount(int64(n))
}
}
// KeyAction will synthesize a keyDown, char, and keyUp event for each rune
2017-02-08 14:35:12 +00:00
// contained in keys along with any supplied key options.
//
// Only well-known, "printable" characters will have char events synthesized.
//
// Please see the chromedp/kb package for implementation details and the list
// of well-known keys.
func KeyAction(keys string, opts ...KeyOption) Action {
return ActionFunc(func(ctxt context.Context, h cdp.Handler) error {
var err error
for _, r := range keys {
for _, k := range kb.Encode(r) {
err = k.Do(ctxt, h)
if err != nil {
return err
}
2017-01-24 15:09:23 +00:00
}
// TODO: move to context
time.Sleep(5 * time.Millisecond)
2017-01-24 15:09:23 +00:00
}
return nil
})
}
// KeyActionNode dispatches a key event on a node.
func KeyActionNode(n *cdp.Node, keys string, opts ...KeyOption) Action {
return ActionFunc(func(ctxt context.Context, h cdp.Handler) error {
err := dom.Focus(n.NodeID).Do(ctxt, h)
2017-01-24 15:09:23 +00:00
if err != nil {
return err
}
return KeyAction(keys, opts...).Do(ctxt, h)
})
2017-01-24 15:09:23 +00:00
}
// KeyOption is a key action option.
type KeyOption func(*input.DispatchKeyEventParams) *input.DispatchKeyEventParams
// KeyModifiers is a key action option to add additional modifiers on the key
// press.
func KeyModifiers(modifiers ...input.Modifier) KeyOption {
return func(p *input.DispatchKeyEventParams) *input.DispatchKeyEventParams {
for _, m := range modifiers {
p.Modifiers |= m
}
return p
}
}