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_ratio_ = opt_options.left_start_ratio; 18 this.top_start_ratio_ = opt_options.top_start_ratio; 19 this.direction_ = opt_options.direction; 20 this.speed_ = opt_options.speed; 21 this.gesture_source_type_ = opt_options.gesture_source_type; 22 } else { 23 this.element_ = document.body; 24 this.left_start_ratio_ = 0.5; 25 this.top_start_ratio_ = 0.5; 26 this.direction_ = 'down'; 27 this.speed_ = 800; 28 this.gesture_source_type_ = chrome.gpuBenchmarking.DEFAULT_INPUT; 29 } 30 } 31 32 function supportedByBrowser() { 33 return !!(window.chrome && 34 chrome.gpuBenchmarking && 35 chrome.gpuBenchmarking.smoothScrollBy); 36 } 37 38 // This class scrolls a page from the top to the bottom once. 39 // 40 // The page is scrolled down by a single scroll gesture. 41 function ScrollAction(opt_callback, opt_distance_func) { 42 var self = this; 43 44 this.beginMeasuringHook = function() {} 45 this.endMeasuringHook = function() {} 46 47 this.callback_ = opt_callback; 48 this.distance_func_ = opt_distance_func; 49 } 50 51 ScrollAction.prototype.getScrollDistance_ = function() { 52 if (this.distance_func_) 53 return this.distance_func_(); 54 55 if (this.options_.direction_ == 'down') { 56 var clientHeight; 57 // clientHeight is "special" for the body element. 58 if (this.element_ == document.body) 59 clientHeight = window.innerHeight; 60 else 61 clientHeight = this.element_.clientHeight; 62 63 return this.element_.scrollHeight - 64 this.element_.scrollTop - 65 clientHeight; 66 } else if (this.options_.direction_ == 'up') { 67 return this.element_.scrollTop; 68 } else if (this.options_.direction_ == 'right') { 69 var clientWidth; 70 // clientWidth is "special" for the body element. 71 if (this.element_ == document.body) 72 clientWidth = window.innerWidth; 73 else 74 clientWidth = this.element_.clientWidth; 75 76 return this.element_.scrollWidth - this.element_.scrollLeft - clientWidth; 77 } else if (this.options_.direction_ == 'left') { 78 return this.element_.scrollLeft; 79 } 80 } 81 82 ScrollAction.prototype.start = function(opt_options) { 83 this.options_ = new ScrollGestureOptions(opt_options); 84 // Assign this.element_ here instead of constructor, because the constructor 85 // ensures this method will be called after the document is loaded. 86 this.element_ = this.options_.element_; 87 requestAnimationFrame(this.startGesture_.bind(this)); 88 }; 89 90 ScrollAction.prototype.startGesture_ = function() { 91 this.beginMeasuringHook(); 92 93 var distance = Math.min(MAX_SCROLL_LENGTH_PIXELS, 94 this.getScrollDistance_()); 95 96 var rect = __GestureCommon_GetBoundingVisibleRect(this.options_.element_); 97 var start_left = 98 rect.left + rect.width * this.options_.left_start_ratio_; 99 var start_top = 100 rect.top + rect.height * this.options_.top_start_ratio_; 101 chrome.gpuBenchmarking.smoothScrollBy( 102 distance, this.onGestureComplete_.bind(this), start_left, start_top, 103 this.options_.gesture_source_type_, this.options_.direction_, 104 this.options_.speed_); 105 }; 106 107 ScrollAction.prototype.onGestureComplete_ = function() { 108 this.endMeasuringHook(); 109 110 // We're done. 111 if (this.callback_) 112 this.callback_(); 113 }; 114 115 window.__ScrollAction = ScrollAction; 116 window.__ScrollAction_SupportedByBrowser = supportedByBrowser; 117})(); 118