1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This file provides the ScrollAction object, which scrolls a page
6// to the bottom or for a specified distance:
7//   1. var action = new __ScrollAction(callback, opt_distance_func)
8//   2. action.start(scroll_options)
9'use strict';
10
11(function() {
12  var MAX_SCROLL_LENGTH_PIXELS = 5000;
13
14  function ScrollGestureOptions(opt_options) {
15    if (opt_options) {
16      this.element_ = opt_options.element;
17      this.left_start_percentage_ = opt_options.left_start_percentage;
18      this.top_start_percentage_ = opt_options.top_start_percentage;
19      this.direction_ = opt_options.direction;
20      this.gesture_source_type_ = opt_options.gesture_source_type;
21    } else {
22      this.element_ = document.body;
23      this.left_start_percentage_ = 0.5;
24      this.top_start_percentage_ = 0.5;
25      this.direction_ = 'down';
26      this.gesture_source_type_ = chrome.gpuBenchmarking.DEFAULT_INPUT;
27    }
28  }
29
30  function supportedByBrowser() {
31    return !!(window.chrome &&
32              chrome.gpuBenchmarking &&
33              chrome.gpuBenchmarking.smoothScrollBy);
34  }
35
36  // This class scrolls a page from the top to the bottom once.
37  //
38  // The page is scrolled down by a single scroll gesture.
39  function ScrollAction(opt_callback, opt_distance_func) {
40    var self = this;
41
42    this.beginMeasuringHook = function() {}
43    this.endMeasuringHook = function() {}
44
45    this.callback_ = opt_callback;
46    this.distance_func_ = opt_distance_func;
47  }
48
49  ScrollAction.prototype.getScrollDistance_ = function() {
50    if (this.distance_func_)
51      return this.distance_func_();
52
53    if (this.options_.direction_ == 'down') {
54      var clientHeight;
55      // clientHeight is "special" for the body element.
56      if (this.element_ == document.body)
57        clientHeight = window.innerHeight;
58      else
59        clientHeight = this.element_.clientHeight;
60
61      return this.element_.scrollHeight -
62             this.element_.scrollTop -
63             clientHeight;
64    } else if (this.options_.direction_ == 'up') {
65      return this.element_.scrollTop;
66    } else if (this.options_.direction_ == 'right') {
67      var clientWidth;
68      // clientWidth is "special" for the body element.
69      if (this.element_ == document.body)
70        clientWidth = window.innerWidth;
71      else
72        clientWidth = this.element_.clientWidth;
73
74      return this.element_.scrollWidth - this.element_.scrollLeft - clientWidth;
75    } else if (this.options_.direction_ == 'left') {
76      return this.element_.scrollLeft;
77    }
78  }
79
80  ScrollAction.prototype.start = function(opt_options) {
81    this.options_ = new ScrollGestureOptions(opt_options);
82    // Assign this.element_ here instead of constructor, because the constructor
83    // ensures this method will be called after the document is loaded.
84    this.element_ = this.options_.element_;
85    requestAnimationFrame(this.startGesture_.bind(this));
86  };
87
88  ScrollAction.prototype.startGesture_ = function() {
89    this.beginMeasuringHook();
90
91    var distance = Math.min(MAX_SCROLL_LENGTH_PIXELS,
92                            this.getScrollDistance_());
93
94    var rect = __GestureCommon_GetBoundingVisibleRect(this.options_.element_);
95    var start_left =
96        rect.left + rect.width * this.options_.left_start_percentage_;
97    var start_top =
98        rect.top + rect.height * this.options_.top_start_percentage_;
99    chrome.gpuBenchmarking.smoothScrollBy(
100        distance, this.onGestureComplete_.bind(this), start_left, start_top,
101        this.options_.gesture_source_type, this.options_.direction_);
102  };
103
104  ScrollAction.prototype.onGestureComplete_ = function() {
105    this.endMeasuringHook();
106
107    // We're done.
108    if (this.callback_)
109      this.callback_();
110  };
111
112  window.__ScrollAction = ScrollAction;
113  window.__ScrollAction_SupportedByBrowser = supportedByBrowser;
114})();
115