File: scroll.rb

package info (click to toggle)
ruby-capybara 3.40.0%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,368 kB
  • sloc: ruby: 23,988; javascript: 752; makefile: 11
file content (76 lines) | stat: -rw-r--r-- 2,144 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# frozen_string_literal: true

module Capybara
  module Selenium
    module Scroll
      def scroll_by(x, y)
        driver.execute_script <<~JS, self, x, y
          var el = arguments[0];
          if (el.scrollBy){
            el.scrollBy(arguments[1], arguments[2]);
          } else {
            el.scrollTop = el.scrollTop + arguments[2];
            el.scrollLeft = el.scrollLeft + arguments[1];
          }
        JS
      end

      def scroll_to(element, location, position = nil)
        # location, element = element, nil if element.is_a? Symbol
        if element.is_a? Capybara::Selenium::Node
          scroll_element_to_location(element, location)
        elsif location.is_a? Symbol
          scroll_to_location(location)
        else
          scroll_to_coords(*position)
        end
        self
      end

    private

      def scroll_element_to_location(element, location)
        scroll_opts = case location
        when :top
          'true'
        when :bottom
          'false'
        when :center
          "{behavior: 'instant', block: 'center'}"
        else
          raise ArgumentError, "Invalid scroll_to location: #{location}"
        end
        driver.execute_script <<~JS, element
          arguments[0].scrollIntoView(#{scroll_opts})
        JS
      end

      SCROLL_POSITIONS = {
        top: '0',
        bottom: 'arguments[0].scrollHeight',
        center: '(arguments[0].scrollHeight - arguments[0].clientHeight)/2'
      }.freeze

      def scroll_to_location(location)
        driver.execute_script <<~JS, self
          if (arguments[0].scrollTo){
            arguments[0].scrollTo(0, #{SCROLL_POSITIONS[location]});
          } else {
            arguments[0].scrollTop = #{SCROLL_POSITIONS[location]};
          }
        JS
      end

      def scroll_to_coords(x, y)
        driver.execute_script <<~JS, self, x, y
          if (arguments[0].scrollTo){
            arguments[0].scrollTo(arguments[1], arguments[2]);
          } else {
            arguments[0].scrollTop = arguments[2];
            arguments[0].scrollLeft = arguments[1];
          }
        JS
      end
    end
  end
end