Home | History | Annotate | Download | only in actions
      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