Esempio n. 1
0
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:
            # TODO(catapult:#3028): Fix interpolation of JavaScript values.
            element = 'document.querySelector("%s")' % self._selector
        else:
            element = self._element_function

        # TODO(catapult:#3028): Fix interpolation of JavaScript values.
        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)
Esempio n. 2
0
class ScrollToElementAction(page_action.PageAction):


  def __init__(self, selector=None, element_function=None,
               container_selector=None, container_element_function=None,
               speed_in_pixels_per_second=800):
    """Perform scroll gesture on container until an element is in view.

    Both the element and the container can be specified by a CSS selector
    xor a JavaScript function, provided as a string, which returns an element.
    The element is required so exactly one of selector and element_function
    must be provided. The container is optional so at most one of
    container_selector and container_element_function can be provided.
    The container defaults to document.scrollingElement or document.body if
    scrollingElement is not set.

    Args:
      selector: A CSS selector describing the element.
      element_function: A JavaScript function (as string) that is used
          to retrieve the element. For example:
          'function() { return foo.element; }'.
      container_selector: A CSS selector describing the container element.
      container_element_function: A JavaScript function (as a string) that is
          used to retrieve the container element.
      speed_in_pixels_per_second: Speed to scroll.
    """
    super(ScrollToElementAction, self).__init__()
    self._selector = selector
    self._element_function = element_function
    self._container_selector = container_selector
    self._container_element_function = container_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 = js_template.Render(
          'document.querySelector({{ selector }})', selector=self._selector)
    else:
      element = self._element_function

    self._distance = tab.EvaluateJavaScript('''
        (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;
        })({{ @element }});
        ''', element=element)
    self._direction = 'down' if self._distance > 0 else 'up'
    self._distance = abs(self._distance)
    self._scroller = ScrollAction(
        direction=self._direction,
        selector=self._container_selector,
        element_function=self._container_element_function,
        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)