Index: telemetry/telemetry/internal/actions/scroll_to_element.py |
diff --git a/telemetry/telemetry/internal/actions/scroll_to_element.py b/telemetry/telemetry/internal/actions/scroll_to_element.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..35732e6afe5d793ee038d73a81950f3442b0c622 |
--- /dev/null |
+++ b/telemetry/telemetry/internal/actions/scroll_to_element.py |
@@ -0,0 +1,60 @@ |
+# Copyright 2015 The Chromium Authors. All rights reserved. |
charliea (OOO until 10-5)
2016/10/14 03:34:28
2016
rnephew (Reviews Here)
2016/10/14 17:57:18
Done.
|
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+from telemetry.internal.actions import page_action |
+from telemetry.internal.actions.scroll import ScrollAction |
+ |
+ |
+class ScrollToElementAction(page_action.PageAction): |
+ |
+ |
+ def __init__(self, selector=None, element_function=None, timeout=60, |
+ speed=None): |
charliea (OOO until 10-5)
2016/10/14 03:34:28
What is |speed| in this case? The number of pixels
rnephew (Reviews Here)
2016/10/14 17:57:18
Done.
|
+ super(ScrollToElementAction, self).__init__() |
+ self._selector = selector |
+ self._element_function = element_function |
+ self._timeout = timeout |
+ self._speed = speed |
+ self._distance = None |
+ self._direction = None |
+ assert (self._selector or self._element_function), ( |
+ 'Must have either selector or element function') |
+ |
+ def WillRunAction(self, tab): |
+ if self._selector: |
+ element = 'document.querySelector("%s")' % self._selector |
+ else: |
+ element = self._element_function |
+ |
+ js = ''' |
charliea (OOO until 10-5)
2016/10/14 03:34:28
Maybe get_distance_js?
rnephew (Reviews Here)
2016/10/14 17:57:18
Done.
|
+ f = ( |
charliea (OOO until 10-5)
2016/10/14 03:34:28
can you just do:
(elem) => {
// Your function c
rnephew (Reviews Here)
2016/10/14 17:57:18
Done.
|
+ (elem) => { |
+ var rect = elem.getBoundingClientRect(); |
+ if (rect.bottom < 0) { |
+ // The bottom of the element is above the viewport. |
+ // Scroll up until the top of the element is on screen. |
+ return rect.top + (window.innerHeight / 2); |
rnephew (Reviews Here)
2016/10/14 17:57:18
rect.top is a negative number here, so need to sub
|
+ } |
+ if (rect.top - window.innerHeight >= 0) { |
+ // rect.top provides the pixel offset of the element from the |
+ // top of the page. Because that exceeds the viewport's height, |
+ // we know that the element is below the viewport. |
+ return rect.top - (window.innerHeight / 2); |
+ } |
+ return 0 |
charliea (OOO until 10-5)
2016/10/14 03:34:28
nit: needs a semicolon
rnephew (Reviews Here)
2016/10/14 17:57:18
Done.
|
+ }) |
+ f(%s); |
nednguyen
2016/10/13 23:16:12
If we can compute the distance here, why not also
rnephew (Reviews Here)
2016/10/14 00:13:18
I was trying to reuse code to limit the complexity
nednguyen
2016/10/14 00:19:02
The round trip mostly will cause more delay & extr
|
+ ''' % element |
+ |
+ self._distance = tab.EvaluateJavaScript(js) |
+ self._direction = 'down' if self._distance > 0 else 'up' |
+ self._distance = abs(self._distance) |
+ |
+ |
+ def RunAction(self, tab): |
+ if self._distance == 0: # Element is already in view. |
+ return |
+ scroller = ScrollAction(direction=self._direction, distance=self._distance) |
+ scroller.WillRunAction(tab) |
charliea (OOO until 10-5)
2016/10/14 03:34:28
I'm not 100% sure, but it seems like we might want
rnephew (Reviews Here)
2016/10/14 17:57:18
Done.
|
+ scroller.RunAction(tab) |