- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / net_internals / horizontal_scrollbar_view.js
1 // Copyright (c) 2011 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 /**
6  * This view consists of two nested divs.  The outer one has a horizontal
7  * scrollbar and the inner one has a height of 1 pixel and a width set to
8  * allow an appropriate scroll range.  The view reports scroll events to
9  * a callback specified on construction.
10  *
11  * All this funkiness is necessary because there is no HTML scroll control.
12  * TODO(mmenke):  Consider implementing our own scrollbar directly.
13  */
14 var HorizontalScrollbarView = (function() {
15   'use strict';
16
17   // We inherit from DivView.
18   var superClass = DivView;
19
20   /**
21    * @constructor
22    */
23   function HorizontalScrollbarView(divId, innerDivId, callback) {
24     superClass.call(this, divId);
25     this.callback_ = callback;
26     this.innerDiv_ = $(innerDivId);
27     $(divId).onscroll = this.onScroll_.bind(this);
28
29     // The current range and position of the scrollbar.  Because DOM updates
30     // are asynchronous, the current state cannot be read directly from the DOM
31     // after updating the range.
32     this.range_ = 0;
33     this.position_ = 0;
34
35     // The DOM updates asynchronously, so sometimes we need a timer to update
36     // the current scroll position after resizing the scrollbar.
37     this.updatePositionTimerId_ = null;
38   }
39
40   HorizontalScrollbarView.prototype = {
41     // Inherit the superclass's methods.
42     __proto__: superClass.prototype,
43
44     setGeometry: function(left, top, width, height) {
45       superClass.prototype.setGeometry.call(this, left, top, width, height);
46       this.setRange(this.range_);
47     },
48
49     show: function(isVisible) {
50       superClass.prototype.show.call(this, isVisible);
51     },
52
53     /**
54      * Sets the range of the scrollbar.  The scrollbar can have a value
55      * anywhere from 0 to |range|, inclusive.  The width of the drag area
56      * on the scrollbar will generally be based on the width of the scrollbar
57      * relative to the size of |range|, so if the scrollbar is about the size
58      * of the thing we're scrolling, we get fairly nice behavior.
59      *
60      * If |range| is less than the original position, |position_| is set to
61      * |range|.  Otherwise, it is not modified.
62      */
63     setRange: function(range) {
64       this.range_ = range;
65       setNodeWidth(this.innerDiv_, this.getWidth() + range);
66       if (range < this.position_)
67         this.position_ = range;
68       this.setPosition(this.position_);
69     },
70
71     /**
72      * Sets the position of the scrollbar.  |position| must be between 0 and
73      * |range_|, inclusive.
74      */
75     setPosition: function(position) {
76       this.position_ = position;
77       this.updatePosition_();
78     },
79
80     /**
81      * Updates the visible position of the scrollbar to be |position_|.
82      * On failure, calls itself again after a timeout.  This is needed because
83      * setRange does not synchronously update the DOM.
84      */
85     updatePosition_: function() {
86       // Clear the timer if we have one, so we don't have two timers running at
87       // once.  This is safe even if we were just called from the timer, in
88       // which case clearTimeout will silently fail.
89       if (this.updatePositionTimerId_ !== null) {
90         window.clearTimeout(this.updatePositionTimerId_);
91         this.updatePositionTimerId_ = null;
92       }
93
94       this.getNode().scrollLeft = this.position_;
95       if (this.getNode().scrollLeft != this.position_) {
96         this.updatePositionTimerId_ =
97             window.setTimeout(this.updatePosition_.bind(this));
98       }
99     },
100
101     getRange: function() {
102       return this.range_;
103     },
104
105     getPosition: function() {
106       return this.position_;
107     },
108
109     onScroll_: function() {
110       // If we're waiting to update the range, ignore messages from the
111       // scrollbar.
112       if (this.updatePositionTimerId_ !== null)
113         return;
114       var newPosition = this.getNode().scrollLeft;
115       if (newPosition == this.position_)
116         return;
117       this.position_ = newPosition;
118       this.callback_();
119     }
120   };
121
122   return HorizontalScrollbarView;
123 })();