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