|
OLD | NEW |
---|---|
(Empty) | |
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(div, innerDiv, callback) { | |
eroman
2011/11/16 04:03:46
nit: innerDiv --> innerDivId; div --> divId
mmenke
2011/11/16 18:39:35
Done.
| |
24 superClass.call(this, div); | |
25 this.callback_ = callback; | |
26 this.innerDiv_ = $(innerDiv); | |
27 $(div).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 up to, and including, |range|. The width of the drag | |
56 * area on the scrollbar will generally be based on the width of the | |
57 * scrollbar relative to the size of |range|, so if the scrollbar is about | |
58 * the size 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 * setPosition does not synchronously update the DOM. | |
84 */ | |
85 updatePosition_: function() { | |
86 // Clear timer if we have one, so we don't have two timers running at | |
87 // once, fighting over the position. Note that this is safe even if | |
88 // we were just call from the timer, in which case clearTimeout will | |
eroman
2011/11/16 04:03:46
nit: "just call from" --> "just called from".
mmenke
2011/11/16 18:39:35
Done.
| |
89 // silently fail. | |
90 if (this.updatePositionTimerId_ !== null) { | |
91 window.clearTimeout(this.updatePositionTimerId_); | |
92 this.updatePositionTimerId_ = null; | |
93 } | |
94 | |
95 this.getNode().scrollLeft = this.position_; | |
96 if (this.getNode().scrollLeft != this.position_) { | |
97 this.updatePositionTimerId_ = | |
98 window.setTimeout(this.updatePosition_.bind(this)); | |
99 } | |
100 }, | |
101 | |
102 getRange: function() { | |
103 return this.range_; | |
104 }, | |
105 | |
106 getPosition: function() { | |
107 return this.position_; | |
108 }, | |
109 | |
110 onScroll_: function() { | |
111 // If we're waiting to update the range, ignore messages from the | |
112 // scrollbar. | |
113 if (this.updatePositionTimerId_ !== null) | |
114 return; | |
115 var newPosition = this.getNode().scrollLeft; | |
116 if (newPosition == this.position_) | |
117 return; | |
118 this.position_ = newPosition; | |
119 this.callback_(); | |
120 } | |
121 }; | |
122 | |
123 return HorizontalScrollbarView; | |
124 })(); | |
OLD | NEW |