4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-layout-container-boxOverflow-Scroller'>/**
19 </span> * @class Ext.layout.container.boxOverflow.Scroller
20 * @extends Ext.layout.container.boxOverflow.None
23 Ext.define('Ext.layout.container.boxOverflow.Scroller', {
25 /* Begin Definitions */
27 extend: 'Ext.layout.container.boxOverflow.None',
28 requires: ['Ext.util.ClickRepeater', 'Ext.Element'],
29 alternateClassName: 'Ext.layout.boxOverflow.Scroller',
31 observable: 'Ext.util.Observable'
36 <span id='Ext-layout-container-boxOverflow-Scroller-cfg-animateScroll'> /**
37 </span> * @cfg {Boolean} animateScroll
38 * True to animate the scrolling of items within the layout (ignored if enableScroll is false)
42 <span id='Ext-layout-container-boxOverflow-Scroller-cfg-scrollIncrement'> /**
43 </span> * @cfg {Number} scrollIncrement
44 * The number of pixels to scroll by on scroller click
48 <span id='Ext-layout-container-boxOverflow-Scroller-cfg-wheelIncrement'> /**
49 </span> * @cfg {Number} wheelIncrement
50 * The number of pixels to increment on mouse wheel scrolling.
54 <span id='Ext-layout-container-boxOverflow-Scroller-cfg-scrollRepeatInterval'> /**
55 </span> * @cfg {Number} scrollRepeatInterval
56 * Number of milliseconds between each scroll while a scroller button is held down
58 scrollRepeatInterval: 60,
60 <span id='Ext-layout-container-boxOverflow-Scroller-cfg-scrollDuration'> /**
61 </span> * @cfg {Number} scrollDuration
62 * Number of milliseconds that each scroll animation lasts
66 <span id='Ext-layout-container-boxOverflow-Scroller-cfg-beforeCtCls'> /**
67 </span> * @cfg {String} beforeCtCls
68 * CSS class added to the beforeCt element. This is the element that holds any special items such as scrollers,
69 * which must always be present at the leftmost edge of the Container
72 <span id='Ext-layout-container-boxOverflow-Scroller-cfg-afterCtCls'> /**
73 </span> * @cfg {String} afterCtCls
74 * CSS class added to the afterCt element. This is the element that holds any special items such as scrollers,
75 * which must always be present at the rightmost edge of the Container
78 <span id='Ext-layout-container-boxOverflow-Scroller-cfg-scrollerCls'> /**
79 </span> * @cfg {String} [scrollerCls='x-box-scroller']
80 * CSS class added to both scroller elements if enableScroll is used
82 scrollerCls: Ext.baseCSSPrefix + 'box-scroller',
84 <span id='Ext-layout-container-boxOverflow-Scroller-cfg-beforeScrollerCls'> /**
85 </span> * @cfg {String} beforeScrollerCls
86 * CSS class added to the left scroller element if enableScroll is used
89 <span id='Ext-layout-container-boxOverflow-Scroller-cfg-afterScrollerCls'> /**
90 </span> * @cfg {String} afterScrollerCls
91 * CSS class added to the right scroller element if enableScroll is used
94 constructor: function(layout, config) {
96 Ext.apply(this, config || {});
99 <span id='Ext-layout-container-boxOverflow-Scroller-event-scroll'> /**
100 </span> * @event scroll
101 * @param {Ext.layout.container.boxOverflow.Scroller} scroller The layout scroller
102 * @param {Number} newPosition The new position of the scroller
103 * @param {Boolean/Object} animate If animating or not. If true, it will be a animation configuration, else it will be false
109 initCSSClasses: function() {
113 if (!me.CSSinitialized) {
114 me.beforeCtCls = me.beforeCtCls || Ext.baseCSSPrefix + 'box-scroller-' + layout.parallelBefore;
115 me.afterCtCls = me.afterCtCls || Ext.baseCSSPrefix + 'box-scroller-' + layout.parallelAfter;
116 me.beforeScrollerCls = me.beforeScrollerCls || Ext.baseCSSPrefix + layout.owner.getXType() + '-scroll-' + layout.parallelBefore;
117 me.afterScrollerCls = me.afterScrollerCls || Ext.baseCSSPrefix + layout.owner.getXType() + '-scroll-' + layout.parallelAfter;
118 me.CSSinitializes = true;
122 handleOverflow: function(calculations, targetSize) {
125 methodName = 'get' + layout.parallelPrefixCap,
129 me.callParent(arguments);
130 this.createInnerElements();
131 this.showScrollers();
132 newSize[layout.perpendicularPrefix] = targetSize[layout.perpendicularPrefix];
133 newSize[layout.parallelPrefix] = targetSize[layout.parallelPrefix] - (me.beforeCt[methodName]() + me.afterCt[methodName]());
134 return { targetSize: newSize };
137 <span id='Ext-layout-container-boxOverflow-Scroller-method-createInnerElements'> /**
139 * Creates the beforeCt and afterCt elements if they have not already been created
141 createInnerElements: function() {
143 target = me.layout.getRenderTarget();
145 //normal items will be rendered to the innerCt. beforeCt and afterCt allow for fixed positioning of
146 //special items such as scrollers or dropdown menu triggers
148 target.addCls(Ext.baseCSSPrefix + me.layout.direction + '-box-overflow-body');
149 me.beforeCt = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.beforeCtCls}, 'before');
150 me.afterCt = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.afterCtCls}, 'after');
151 me.createWheelListener();
155 <span id='Ext-layout-container-boxOverflow-Scroller-method-createWheelListener'> /**
157 * Sets up an listener to scroll on the layout's innerCt mousewheel event
159 createWheelListener: function() {
160 this.layout.innerCt.on({
162 mousewheel: function(e) {
165 this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);
170 <span id='Ext-layout-container-boxOverflow-Scroller-method-clearOverflow'> /**
173 clearOverflow: function() {
174 this.hideScrollers();
177 <span id='Ext-layout-container-boxOverflow-Scroller-method-showScrollers'> /**
179 * Shows the scroller elements in the beforeCt and afterCt. Creates the scrollers first if they are not already
182 showScrollers: function() {
183 this.createScrollers();
184 this.beforeScroller.show();
185 this.afterScroller.show();
186 this.updateScrollButtons();
188 this.layout.owner.addClsWithUI('scroller');
191 <span id='Ext-layout-container-boxOverflow-Scroller-method-hideScrollers'> /**
193 * Hides the scroller elements in the beforeCt and afterCt
195 hideScrollers: function() {
196 if (this.beforeScroller != undefined) {
197 this.beforeScroller.hide();
198 this.afterScroller.hide();
200 this.layout.owner.removeClsWithUI('scroller');
204 <span id='Ext-layout-container-boxOverflow-Scroller-method-createScrollers'> /**
206 * Creates the clickable scroller elements and places them into the beforeCt and afterCt
208 createScrollers: function() {
209 if (!this.beforeScroller && !this.afterScroller) {
210 var before = this.beforeCt.createChild({
211 cls: Ext.String.format("{0} {1} ", this.scrollerCls, this.beforeScrollerCls)
214 var after = this.afterCt.createChild({
215 cls: Ext.String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
218 before.addClsOnOver(this.beforeScrollerCls + '-hover');
219 after.addClsOnOver(this.afterScrollerCls + '-hover');
221 before.setVisibilityMode(Ext.Element.DISPLAY);
222 after.setVisibilityMode(Ext.Element.DISPLAY);
224 this.beforeRepeater = Ext.create('Ext.util.ClickRepeater', before, {
225 interval: this.scrollRepeatInterval,
226 handler : this.scrollLeft,
230 this.afterRepeater = Ext.create('Ext.util.ClickRepeater', after, {
231 interval: this.scrollRepeatInterval,
232 handler : this.scrollRight,
236 <span id='Ext-layout-container-boxOverflow-Scroller-property-beforeScroller'> /**
237 </span> * @property beforeScroller
239 * The left scroller element. Only created when needed.
241 this.beforeScroller = before;
243 <span id='Ext-layout-container-boxOverflow-Scroller-property-afterScroller'> /**
244 </span> * @property afterScroller
246 * The left scroller element. Only created when needed.
248 this.afterScroller = after;
252 <span id='Ext-layout-container-boxOverflow-Scroller-method-destroy'> /**
255 destroy: function() {
256 Ext.destroy(this.beforeRepeater, this.afterRepeater, this.beforeScroller, this.afterScroller, this.beforeCt, this.afterCt);
259 <span id='Ext-layout-container-boxOverflow-Scroller-method-scrollBy'> /**
261 * Scrolls left or right by the number of pixels specified
262 * @param {Number} delta Number of pixels to scroll to the right by. Use a negative number to scroll left
264 scrollBy: function(delta, animate) {
265 this.scrollTo(this.getScrollPosition() + delta, animate);
268 <span id='Ext-layout-container-boxOverflow-Scroller-method-getScrollAnim'> /**
270 * @return {Object} Object passed to scrollTo when scrolling
272 getScrollAnim: function() {
274 duration: this.scrollDuration,
275 callback: this.updateScrollButtons,
280 <span id='Ext-layout-container-boxOverflow-Scroller-method-updateScrollButtons'> /**
282 * Enables or disables each scroller button based on the current scroll position
284 updateScrollButtons: function() {
285 if (this.beforeScroller == undefined || this.afterScroller == undefined) {
289 var beforeMeth = this.atExtremeBefore() ? 'addCls' : 'removeCls',
290 afterMeth = this.atExtremeAfter() ? 'addCls' : 'removeCls',
291 beforeCls = this.beforeScrollerCls + '-disabled',
292 afterCls = this.afterScrollerCls + '-disabled';
294 this.beforeScroller[beforeMeth](beforeCls);
295 this.afterScroller[afterMeth](afterCls);
296 this.scrolling = false;
299 <span id='Ext-layout-container-boxOverflow-Scroller-method-atExtremeBefore'> /**
301 * Returns true if the innerCt scroll is already at its left-most point
302 * @return {Boolean} True if already at furthest left point
304 atExtremeBefore: function() {
305 return this.getScrollPosition() === 0;
308 <span id='Ext-layout-container-boxOverflow-Scroller-method-scrollLeft'> /**
310 * Scrolls to the left by the configured amount
312 scrollLeft: function() {
313 this.scrollBy(-this.scrollIncrement, false);
316 <span id='Ext-layout-container-boxOverflow-Scroller-method-scrollRight'> /**
318 * Scrolls to the right by the configured amount
320 scrollRight: function() {
321 this.scrollBy(this.scrollIncrement, false);
324 <span id='Ext-layout-container-boxOverflow-Scroller-method-getScrollPosition'> /**
325 </span> * Returns the current scroll position of the innerCt element
326 * @return {Number} The current scroll position
328 getScrollPosition: function(){
329 var layout = this.layout;
330 return parseInt(layout.innerCt.dom['scroll' + layout.parallelBeforeCap], 10) || 0;
333 <span id='Ext-layout-container-boxOverflow-Scroller-method-getMaxScrollPosition'> /**
335 * Returns the maximum value we can scrollTo
336 * @return {Number} The max scroll value
338 getMaxScrollPosition: function() {
339 var layout = this.layout;
340 return layout.innerCt.dom['scroll' + layout.parallelPrefixCap] - this.layout.innerCt['get' + layout.parallelPrefixCap]();
343 <span id='Ext-layout-container-boxOverflow-Scroller-method-atExtremeAfter'> /**
345 * Returns true if the innerCt scroll is already at its right-most point
346 * @return {Boolean} True if already at furthest right point
348 atExtremeAfter: function() {
349 return this.getScrollPosition() >= this.getMaxScrollPosition();
352 <span id='Ext-layout-container-boxOverflow-Scroller-method-scrollTo'> /**
354 * Scrolls to the given position. Performs bounds checking.
355 * @param {Number} position The position to scroll to. This is constrained.
356 * @param {Boolean} animate True to animate. If undefined, falls back to value of this.animateScroll
358 scrollTo: function(position, animate) {
361 oldPosition = me.getScrollPosition(),
362 newPosition = Ext.Number.constrain(position, 0, me.getMaxScrollPosition());
364 if (newPosition != oldPosition && !me.scrolling) {
365 if (animate == undefined) {
366 animate = me.animateScroll;
369 layout.innerCt.scrollTo(layout.parallelBefore, newPosition, animate ? me.getScrollAnim() : false);
373 me.scrolling = false;
374 me.updateScrollButtons();
377 me.fireEvent('scroll', me, newPosition, animate ? me.getScrollAnim() : false);
381 <span id='Ext-layout-container-boxOverflow-Scroller-method-scrollToItem'> /**
382 </span> * Scrolls to the given component.
383 * @param {String/Number/Ext.Component} item The item to scroll to. Can be a numerical index, component id
384 * or a reference to the component itself.
385 * @param {Boolean} animate True to animate the scrolling
387 scrollToItem: function(item, animate) {
394 item = me.getItem(item);
395 if (item != undefined) {
396 visibility = this.getItemVisibility(item);
397 if (!visibility.fullyVisible) {
398 box = item.getBox(true, true);
399 newPos = box[layout.parallelPosition];
400 if (visibility.hiddenEnd) {
401 newPos -= (this.layout.innerCt['get' + layout.parallelPrefixCap]() - box[layout.parallelPrefix]);
403 this.scrollTo(newPos, animate);
408 <span id='Ext-layout-container-boxOverflow-Scroller-method-getItemVisibility'> /**
410 * For a given item in the container, return an object with information on whether the item is visible
411 * with the current innerCt scroll value.
412 * @param {Ext.Component} item The item
413 * @return {Object} Values for fullyVisible, hiddenStart and hiddenEnd
415 getItemVisibility: function(item) {
417 box = me.getItem(item).getBox(true, true),
419 itemStart = box[layout.parallelPosition],
420 itemEnd = itemStart + box[layout.parallelPrefix],
421 scrollStart = me.getScrollPosition(),
422 scrollEnd = scrollStart + layout.innerCt['get' + layout.parallelPrefixCap]();
425 hiddenStart : itemStart < scrollStart,
426 hiddenEnd : itemEnd > scrollEnd,
427 fullyVisible: itemStart > scrollStart && itemEnd < scrollEnd