| 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..8f6302d1b967d854a2ffdfc9107c3a7e3df7d7b3
|
| --- /dev/null
|
| +++ b/telemetry/telemetry/internal/actions/scroll_to_element.py
|
| @@ -0,0 +1,65 @@
|
| +# Copyright 2016 The Chromium Authors. All rights reserved.
|
| +# 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,
|
| + speed_in_pixels_per_second=800):
|
| + """
|
| + Args:
|
| + selector: Css selector to find element with.
|
| + element_function: js string that evaluates to an element.
|
| + speed_in_pixels_per_second: Speed in pixels per second to scroll.
|
| + """
|
| + super(ScrollToElementAction, self).__init__()
|
| + self._selector = selector
|
| + self._element_function = element_function
|
| + self._speed = speed_in_pixels_per_second
|
| + self._distance = None
|
| + self._direction = None
|
| + self._scroller = 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
|
| +
|
| + get_distance_js = '''
|
| + (function(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);
|
| + }
|
| + 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;
|
| + })(%s);
|
| + ''' % element
|
| +
|
| + self._distance = tab.EvaluateJavaScript(get_distance_js)
|
| + self._direction = 'down' if self._distance > 0 else 'up'
|
| + self._distance = abs(self._distance)
|
| + self._scroller = ScrollAction(direction=self._direction,
|
| + distance=self._distance,
|
| + speed_in_pixels_per_second=self._speed)
|
| +
|
| + def RunAction(self, tab):
|
| + if self._distance == 0: # Element is already in view.
|
| + return
|
| + self._scroller.WillRunAction(tab)
|
| + self._scroller.RunAction(tab)
|
|
|