Changes to ElementVisible/ElementNotVisible

Changed implementation of ElementVisible/ElementNotVisible to use a
javascript evaluation instead of the previous, cumbersome
implementation. As this may not work correctly in all scenarios, the old
versions will remain as ElementVisibleOld and ElementNotVisibleOld until
the new implementations can be vetted for correctness/performance.
This commit is contained in:
Kenneth Shaw 2017-02-08 15:40:22 +07:00
parent b57afce7e7
commit 5bef7dce13
2 changed files with 46 additions and 19 deletions

18
nav.go
View File

@ -3,11 +3,9 @@ package chromedp
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"github.com/knq/chromedp/cdp" "github.com/knq/chromedp/cdp"
"github.com/knq/chromedp/cdp/page" "github.com/knq/chromedp/cdp/page"
rundom "github.com/knq/chromedp/cdp/runtime"
) )
// Navigate navigates the current frame. // Navigate navigates the current frame.
@ -125,20 +123,6 @@ func Location(urlstr *string) Action {
if urlstr == nil { if urlstr == nil {
panic("urlstr cannot be nil") panic("urlstr cannot be nil")
} }
return ActionFunc(func(ctxt context.Context, h cdp.FrameHandler) error {
res, exp, err := rundom.Evaluate(`location.toString()`).Do(ctxt, h)
if err != nil {
return err
}
if exp != nil {
return exp
}
if res.Type != rundom.TypeString || len(res.Value) < 2 {
return fmt.Errorf("expected string of at least length 2, got %s length %d", res.Subtype, len(res.Value))
}
*urlstr = string(res.Value[1 : len(res.Value)-1]) return EvaluateAsDevTools(`location.toString()`, urlstr)
return nil
})
} }

47
sel.go
View File

@ -300,6 +300,38 @@ func ElementReady(s *Selector) {
// ElementVisible is a query option to wait until the element is visible. // ElementVisible is a query option to wait until the element is visible.
func ElementVisible(s *Selector) { func ElementVisible(s *Selector) {
WaitFunc(s.waitReady(func(ctxt context.Context, h cdp.FrameHandler, n *cdp.Node) error {
var res bool
err := EvaluateAsDevTools(fmt.Sprintf(visibleJS, n.FullXPath()), &res).Do(ctxt, h)
if err != nil {
return err
}
if !res {
return ErrNotVisible
}
return nil
}))(s)
}
// ElementNotVisible is a query option to wait until the element is not visible.
func ElementNotVisible(s *Selector) {
WaitFunc(s.waitReady(func(ctxt context.Context, h cdp.FrameHandler, n *cdp.Node) error {
var res bool
err := EvaluateAsDevTools(fmt.Sprintf(visibleJS, n.FullXPath()), &res).Do(ctxt, h)
if err != nil {
return err
}
if res {
return ErrVisible
}
return nil
}))(s)
}
// ElementVisibleOld is a query option to wait until the element is visible.
//
// This is the old, complicated, implementation (deprecated).
func ElementVisibleOld(s *Selector) {
WaitFunc(s.waitReady(func(ctxt context.Context, h cdp.FrameHandler, n *cdp.Node) error { WaitFunc(s.waitReady(func(ctxt context.Context, h cdp.FrameHandler, n *cdp.Node) error {
var err error var err error
@ -344,8 +376,11 @@ func ElementVisible(s *Selector) {
}))(s) }))(s)
} }
// ElementNotVisible is a query option to wait until the element is visible. // ElementNotVisibleOld is a query option to wait until the element is not
func ElementNotVisible(s *Selector) { // visible.
//
// This is the old, complicated, implementation (deprecated).
func ElementNotVisibleOld(s *Selector) {
WaitFunc(s.waitReady(func(ctxt context.Context, h cdp.FrameHandler, n *cdp.Node) error { WaitFunc(s.waitReady(func(ctxt context.Context, h cdp.FrameHandler, n *cdp.Node) error {
var err error var err error
@ -463,3 +498,11 @@ func WaitEnabled(sel interface{}, opts ...QueryOption) Action {
func WaitSelected(sel interface{}, opts ...QueryOption) Action { func WaitSelected(sel interface{}, opts ...QueryOption) Action {
return Query(sel, append(opts, ElementSelected)...) return Query(sel, append(opts, ElementSelected)...)
} }
const (
// visibleJS is a javascript snippet that returns true or false depending
// on if the specified node's offsetParent is not null.
visibleJS = `(function(a) {
return a[0].offsetParent !== null
})($x('%s'))`
)