1 /****************************************************************************
  2  Copyright (c) 2011-2012 cocos2d-x.org
  3  Copyright (c) 2013-2014 Chukong Technologies Inc.
  4 
  5  http://www.cocos2d-x.org
  6 
  7  Permission is hereby granted, free of charge, to any person obtaining a copy
  8  of this software and associated documentation files (the "Software"), to deal
  9  in the Software without restriction, including without limitation the rights
 10  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 11  copies of the Software, and to permit persons to whom the Software is
 12  furnished to do so, subject to the following conditions:
 13 
 14  The above copyright notice and this permission notice shall be included in
 15  all copies or substantial portions of the Software.
 16 
 17  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 18  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 19  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 20  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 21  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 22  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 23  THE SOFTWARE.
 24  ****************************************************************************/
 25 
 26 /**
 27  * The ScrollView control of Cocos UI
 28  * @class
 29  * @extends ccui.Layout
 30  *
 31  * @property {Number}               innerWidth              - Inner container width of the scroll view
 32  * @property {Number}               innerHeight             - Inner container height of the scroll view
 33  * @property {ccui.ScrollView.DIR_NONE | ccui.ScrollView.DIR_VERTICAL | ccui.ScrollView.DIR_HORIZONTAL | ccui.ScrollView.DIR_BOTH}    direction               - Scroll direction of the scroll view
 34  * @property {Boolean}              bounceEnabled           - Indicate whether bounce is enabled
 35  * @property {Boolean}              inertiaScrollEnabled    - Indicate whether inertiaScroll is enabled
 36  */
 37 ccui.ScrollView = ccui.Layout.extend(/** @lends ccui.ScrollView# */{
 38     _innerContainer: null,
 39     direction: null,
 40     _autoScrollDir: null,
 41 
 42     _topBoundary: 0,
 43     _bottomBoundary: 0,
 44     _leftBoundary: 0,
 45     _rightBoundary: 0,
 46 
 47     _bounceTopBoundary: 0,
 48     _bounceBottomBoundary: 0,
 49     _bounceLeftBoundary: 0,
 50     _bounceRightBoundary: 0,
 51 
 52     _autoScroll: false,
 53     _autoScrollAddUpTime: 0,
 54 
 55     _autoScrollOriginalSpeed: 0,
 56     _autoScrollAcceleration: 0,
 57     _isAutoScrollSpeedAttenuated: false,
 58     _needCheckAutoScrollDestination: false,
 59     _autoScrollDestination: null,
 60 
 61     _bePressed: false,
 62     _slidTime: 0,
 63     _moveChildPoint: null,
 64     _childFocusCancelOffset: 0,
 65 
 66     _leftBounceNeeded: false,
 67     _topBounceNeeded: false,
 68     _rightBounceNeeded: false,
 69     _bottomBounceNeeded: false,
 70 
 71     bounceEnabled: false,
 72     _bouncing: false,
 73     _bounceDir: null,
 74     _bounceOriginalSpeed: 0,
 75     inertiaScrollEnabled: false,
 76 
 77     _scrollViewEventListener: null,
 78     _scrollViewEventSelector: null,
 79     _className: "ScrollView",
 80 
 81     /**
 82      * Allocates and initializes a UIScrollView.
 83      * Constructor of ccui.ScrollView. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
 84      * @example
 85      * // example
 86      * var uiScrollView = new ccui.ScrollView();
 87      */
 88     ctor: function () {
 89         ccui.Layout.prototype.ctor.call(this);
 90         this.direction = ccui.ScrollView.DIR_NONE;
 91         this._autoScrollDir = cc.p(0, 0);
 92 
 93         this._autoScrollAcceleration = -1000;
 94         this._autoScrollDestination = cc.p(0, 0);
 95         this._slidTime = 0;
 96         this._moveChildPoint = cc.p(0, 0);
 97         this._childFocusCancelOffset = 5;
 98         this._bounceDir = cc.p(0, 0);
 99         this._bounceOriginalSpeed = 0;
100         this.inertiaScrollEnabled = true;
101         this.setTouchEnabled(true);
102     },
103 
104     /**
105      * Initializes a ccui.ScrollView. Please do not call this function by yourself, you should pass the parameters to constructor to initialize it.
106      * @returns {boolean}
107      */
108     init: function () {
109         if (ccui.Layout.prototype.init.call(this)) {
110             this.setClippingEnabled(true);
111             this._innerContainer.setTouchEnabled(false);
112             return true;
113         }
114         return false;
115     },
116 
117     /**
118      * Calls the parent class' onEnter and schedules update function.
119      * @override
120      */
121     onEnter: function () {
122         ccui.Layout.prototype.onEnter.call(this);
123         this.scheduleUpdate(true);
124     },
125 
126     /**
127      * When a widget is in a layout, you could call this method to get the next focused widget within a specified direction.             <br/>
128      * If the widget is not in a layout, it will return itself
129      *
130      * @param {Number} direction the direction to look for the next focused widget in a layout
131      * @param {ccui.Widget} current the current focused widget
132      * @returns {ccui.Widget}
133      */
134     findNextFocusedWidget: function(direction, current){
135         if (this.getLayoutType() == ccui.Layout.LINEAR_VERTICAL
136             || this.getLayoutType() == ccui.Layout.LINEAR_HORIZONTAL) {
137             return this._innerContainer.findNextFocusedWidget(direction, current);
138         } else
139             return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, current);
140     },
141 
142     _initRenderer: function () {
143         ccui.Layout.prototype._initRenderer.call(this);
144         this._innerContainer = ccui.Layout.create();
145         this.addProtectedChild(this._innerContainer, 1, 1);
146     },
147 
148     _onSizeChanged: function () {
149         ccui.Layout.prototype._onSizeChanged.call(this);
150         var locSize = this._contentSize;
151         this._topBoundary = locSize.height;
152         this._rightBoundary = locSize.width;
153         var bounceBoundaryParameterX = locSize.width / 3;
154         var bounceBoundaryParameterY = locSize.height / 3;
155         this._bounceTopBoundary = locSize.height - bounceBoundaryParameterY;
156         this._bounceBottomBoundary = bounceBoundaryParameterY;
157         this._bounceLeftBoundary = bounceBoundaryParameterX;
158         this._bounceRightBoundary = locSize.width - bounceBoundaryParameterX;
159         var innerSize = this._innerContainer.getContentSize();
160         this._innerContainer.setContentSize(cc.size(Math.max(innerSize.width, locSize.width), Math.max(innerSize.height, locSize.height)));
161         this._innerContainer.setPosition(0, locSize.height - this._innerContainer.getContentSize().height);
162     },
163 
164     /**
165      * Changes inner container size of ScrollView.     <br/>
166      * Inner container size must be larger than or equal the size of ScrollView.
167      * @param {cc.Size} size inner container size.
168      */
169     setInnerContainerSize: function (size) {
170         var innerContainer = this._innerContainer;
171         var locSize = this._contentSize;
172         var innerSizeWidth = locSize.width, innerSizeHeight = locSize.height;
173         var originalInnerSize = innerContainer.getContentSize();
174         if (size.width < locSize.width)
175             cc.log("Inner width <= ScrollView width, it will be force sized!");
176         else
177             innerSizeWidth = size.width;
178 
179         if (size.height < locSize.height)
180             cc.log("Inner height <= ScrollView height, it will be force sized!");
181         else
182             innerSizeHeight = size.height;
183 
184         innerContainer.setContentSize(cc.size(innerSizeWidth, innerSizeHeight));
185         var newInnerSize, offset;
186         switch (this.direction) {
187             case ccui.ScrollView.DIR_VERTICAL:
188                 newInnerSize = innerContainer.getContentSize();
189                 offset = originalInnerSize.height - newInnerSize.height;
190                 this._scrollChildren(0, offset);
191                 break;
192             case ccui.ScrollView.DIR_HORIZONTAL:
193                 if (innerContainer.getRightBoundary() <= locSize.width) {
194                     newInnerSize = innerContainer.getContentSize();
195                     offset = originalInnerSize.width - newInnerSize.width;
196                     this._scrollChildren(offset, 0);
197                 }
198                 break;
199             case ccui.ScrollView.DIR_BOTH:
200                 newInnerSize = innerContainer.getContentSize();
201                 var offsetY = originalInnerSize.height - newInnerSize.height;
202                 var offsetX = (innerContainer.getRightBoundary() <= locSize.width) ? originalInnerSize.width - newInnerSize.width : 0;
203                 this._scrollChildren(offsetX, offsetY);
204                 break;
205             default:
206                 break;
207         }
208 
209         var innerSize = innerContainer.getContentSize();
210         var innerPos = innerContainer.getPosition();
211         var innerAP = innerContainer.getAnchorPoint();
212         if (innerContainer.getLeftBoundary() > 0.0)
213             innerContainer.setPosition(innerAP.x * innerSize.width, innerPos.y);
214         if (innerContainer.getRightBoundary() < locSize.width)
215             innerContainer.setPosition(locSize.width - ((1.0 - innerAP.x) * innerSize.width), innerPos.y);
216         if (innerPos.y > 0.0)
217             innerContainer.setPosition(innerPos.x, innerAP.y * innerSize.height);
218         if (innerContainer.getTopBoundary() < locSize.height)
219             innerContainer.setPosition(innerPos.x, locSize.height - (1.0 - innerAP.y) * innerSize.height);
220     },
221 
222     _setInnerWidth: function (width) {
223         var locW = this._contentSize.width,
224             innerWidth = locW,
225             container = this._innerContainer,
226             oldInnerWidth = container.width;
227         if (width < locW)
228             cc.log("Inner width <= scrollview width, it will be force sized!");
229         else
230             innerWidth = width;
231         container.width = innerWidth;
232 
233         switch (this.direction) {
234             case ccui.ScrollView.DIR_HORIZONTAL:
235             case ccui.ScrollView.DIR_BOTH:
236                 if (container.getRightBoundary() <= locW) {
237                     var newInnerWidth = container.width;
238                     var offset = oldInnerWidth - newInnerWidth;
239                     this._scrollChildren(offset, 0);
240                 }
241                 break;
242         }
243         var innerAX = container.anchorX;
244         if (container.getLeftBoundary() > 0.0)
245             container.x = innerAX * innerWidth;
246         if (container.getRightBoundary() < locW)
247             container.x = locW - ((1.0 - innerAX) * innerWidth);
248     },
249 
250     _setInnerHeight: function (height) {
251         var locH = this._contentSize.height,
252             innerHeight = locH,
253             container = this._innerContainer,
254             oldInnerHeight = container.height;
255         if (height < locH)
256             cc.log("Inner height <= scrollview height, it will be force sized!");
257         else
258             innerHeight = height;
259         container.height = innerHeight;
260 
261         switch (this.direction) {
262             case ccui.ScrollView.DIR_VERTICAL:
263             case ccui.ScrollView.DIR_BOTH:
264                 var newInnerHeight = innerHeight;
265                 var offset = oldInnerHeight - newInnerHeight;
266                 this._scrollChildren(0, offset);
267                 break;
268         }
269         var innerAY = container.anchorY;
270         if (container.getLeftBoundary() > 0.0)
271             container.y = innerAY * innerHeight;
272         if (container.getRightBoundary() < locH)
273             container.y = locH - ((1.0 - innerAY) * innerHeight);
274     },
275 
276     /**
277      * Returns inner container size of ScrollView.     <br/>
278      * Inner container size must be larger than or equal ScrollView's size.
279      *
280      * @return {cc.Size} inner container size.
281      */
282     getInnerContainerSize: function () {
283         return this._innerContainer.getContentSize();
284     },
285     _getInnerWidth: function () {
286         return this._innerContainer.width;
287     },
288     _getInnerHeight: function () {
289         return this._innerContainer.height;
290     },
291 
292     /**
293      * Add child to ccui.ScrollView.
294      * @param {cc.Node} widget
295      * @param {Number} [zOrder]
296      * @param {Number|string} [tag] tag or name
297      * @returns {boolean}
298      */
299     addChild: function (widget, zOrder, tag) {
300         if(!widget)
301             return false;
302         zOrder = zOrder || widget.getLocalZOrder();
303         tag = tag || widget.getTag();
304         return this._innerContainer.addChild(widget, zOrder, tag);
305     },
306 
307     /**
308      * Removes all children.
309      */
310     removeAllChildren: function () {
311         this.removeAllChildrenWithCleanup(true);
312     },
313 
314     /**
315      * Removes all children.
316      * @param {Boolean} cleanup
317      */
318     removeAllChildrenWithCleanup: function(cleanup){
319         this._innerContainer.removeAllChildrenWithCleanup(cleanup);
320     },
321 
322     /**
323      * Removes widget child
324      * @override
325      * @param {ccui.Widget} child
326      * @param {Boolean} cleanup
327      * @returns {boolean}
328      */
329     removeChild: function (child, cleanup) {
330         return this._innerContainer.removeChild(child, cleanup);
331     },
332 
333     /**
334      * Returns inner container's children
335      * @returns {Array}
336      */
337     getChildren: function () {
338         return this._innerContainer.getChildren();
339     },
340 
341     /**
342      * Gets the count of inner container's children
343      * @returns {Number}
344      */
345     getChildrenCount: function () {
346         return this._innerContainer.getChildrenCount();
347     },
348 
349     /**
350      * Gets a child from the container given its tag
351      * @param {Number} tag
352      * @returns {ccui.Widget}
353      */
354     getChildByTag: function (tag) {
355         return this._innerContainer.getChildByTag(tag);
356     },
357 
358     /**
359      * Gets a child from the container given its name
360      * @param {String} name
361      * @returns {ccui.Widget}
362      */
363     getChildByName: function (name) {
364         return this._innerContainer.getChildByName(name);
365     },
366 
367     _moveChildren: function (offsetX, offsetY) {
368         var locContainer = this._innerContainer;
369         //var pos = this._innerContainer.getPosition();
370         this._moveChildPoint.x = locContainer.x + offsetX;
371         this._moveChildPoint.y = locContainer.y + offsetY;
372         this._innerContainer.setPosition(this._moveChildPoint);
373     },
374 
375     _autoScrollChildren: function (dt) {
376         var lastTime = this._autoScrollAddUpTime;
377         this._autoScrollAddUpTime += dt;
378         if (this._isAutoScrollSpeedAttenuated) {
379             var nowSpeed = this._autoScrollOriginalSpeed + this._autoScrollAcceleration * this._autoScrollAddUpTime;
380             if (nowSpeed <= 0) {
381                 this._stopAutoScrollChildren();
382                 this._checkNeedBounce();
383             } else {
384                 var timeParam = lastTime * 2 + dt;
385                 var offset = (this._autoScrollOriginalSpeed + this._autoScrollAcceleration * timeParam * 0.5) * dt;
386                 var offsetX = offset * this._autoScrollDir.x;
387                 var offsetY = offset * this._autoScrollDir.y;
388                 if (!this._scrollChildren(offsetX, offsetY)) {
389                     this._stopAutoScrollChildren();
390                     this._checkNeedBounce();
391                 }
392             }
393         } else {
394             if (this._needCheckAutoScrollDestination) {
395                 var xOffset = this._autoScrollDir.x * dt * this._autoScrollOriginalSpeed;
396                 var yOffset = this._autoScrollDir.y * dt * this._autoScrollOriginalSpeed;
397                 var notDone = this._checkCustomScrollDestination(xOffset, yOffset);
398                 var scrollCheck = this._scrollChildren(xOffset, yOffset);
399                 if (!notDone || !scrollCheck) {
400                     this._stopAutoScrollChildren();
401                     this._checkNeedBounce();
402                 }
403             } else {
404                 if (!this._scrollChildren(this._autoScrollDir.x * dt * this._autoScrollOriginalSpeed,
405                         this._autoScrollDir.y * dt * this._autoScrollOriginalSpeed)) {
406                     this._stopAutoScrollChildren();
407                     this._checkNeedBounce();
408                 }
409             }
410         }
411     },
412 
413     _bounceChildren: function (dt) {
414         var locSpeed = this._bounceOriginalSpeed;
415         var locBounceDir = this._bounceDir;
416         if (locSpeed <= 0.0)
417             this._stopBounceChildren();
418         if (!this._bounceScrollChildren(locBounceDir.x * dt * locSpeed, locBounceDir.y * dt * locSpeed))
419             this._stopBounceChildren();
420     },
421 
422     _checkNeedBounce: function () {
423         if (!this.bounceEnabled)
424             return false;
425         this._checkBounceBoundary();
426         var locTopBounceNeeded = this._topBounceNeeded, locBottomBounceNeeded = this._bottomBounceNeeded,
427             locLeftBounceNeeded = this._leftBounceNeeded, locRightBounceNeeded = this._rightBounceNeeded;
428 
429         if (locTopBounceNeeded || locBottomBounceNeeded || locLeftBounceNeeded || locRightBounceNeeded) {
430             var scrollVector, orSpeed;
431             var locContentSize = this._contentSize, locInnerContainer = this._innerContainer;
432             if (locTopBounceNeeded && locLeftBounceNeeded) {
433                 scrollVector = cc.pSub(cc.p(0.0, locContentSize.height), cc.p(locInnerContainer.getLeftBoundary(), locInnerContainer.getTopBoundary()));
434                 orSpeed = cc.pLength(scrollVector) / 0.2;
435                 this._bounceDir = cc.pNormalize(scrollVector);
436                 this._startBounceChildren(orSpeed);
437             } else if (locTopBounceNeeded && locRightBounceNeeded) {
438                 scrollVector = cc.pSub(cc.p(locContentSize.width, locContentSize.height), cc.p(locInnerContainer.getRightBoundary(), locInnerContainer.getTopBoundary()));
439                 orSpeed = cc.pLength(scrollVector) / 0.2;
440                 this._bounceDir = cc.pNormalize(scrollVector);
441                 this._startBounceChildren(orSpeed);
442             } else if (locBottomBounceNeeded && locLeftBounceNeeded) {
443                 scrollVector = cc.pSub(cc.p(0, 0), cc.p(locInnerContainer.getLeftBoundary(), locInnerContainer.getBottomBoundary()));
444                 orSpeed = cc.pLength(scrollVector) / 0.2;
445                 this._bounceDir = cc.pNormalize(scrollVector);
446                 this._startBounceChildren(orSpeed);
447             } else if (locBottomBounceNeeded && locRightBounceNeeded) {
448                 scrollVector = cc.pSub(cc.p(locContentSize.width, 0.0), cc.p(locInnerContainer.getRightBoundary(), locInnerContainer.getBottomBoundary()));
449                 orSpeed = cc.pLength(scrollVector) / 0.2;
450                 this._bounceDir = cc.pNormalize(scrollVector);
451                 this._startBounceChildren(orSpeed);
452             } else if (locTopBounceNeeded) {
453                 scrollVector = cc.pSub(cc.p(0, locContentSize.height), cc.p(0.0, locInnerContainer.getTopBoundary()));
454                 orSpeed = cc.pLength(scrollVector) / 0.2;
455                 this._bounceDir = cc.pNormalize(scrollVector);
456                 this._startBounceChildren(orSpeed);
457             } else if (locBottomBounceNeeded) {
458                 scrollVector = cc.pSub(cc.p(0, 0), cc.p(0.0, locInnerContainer.getBottomBoundary()));
459                 orSpeed = cc.pLength(scrollVector) / 0.2;
460                 this._bounceDir = cc.pNormalize(scrollVector);
461                 this._startBounceChildren(orSpeed);
462             } else if (locLeftBounceNeeded) {
463                 scrollVector = cc.pSub(cc.p(0, 0), cc.p(locInnerContainer.getLeftBoundary(), 0.0));
464                 orSpeed = cc.pLength(scrollVector) / 0.2;
465                 this._bounceDir = cc.pNormalize(scrollVector);
466                 this._startBounceChildren(orSpeed);
467             } else if (locRightBounceNeeded) {
468                 scrollVector = cc.pSub(cc.p(locContentSize.width, 0), cc.p(locInnerContainer.getRightBoundary(), 0.0));
469                 orSpeed = cc.pLength(scrollVector) / 0.2;
470                 this._bounceDir = cc.pNormalize(scrollVector);
471                 this._startBounceChildren(orSpeed);
472             }
473             return true;
474         }
475         return false;
476     },
477 
478     _checkBounceBoundary: function () {
479         var locContainer = this._innerContainer;
480         var icBottomPos = locContainer.getBottomBoundary();
481         if (icBottomPos > this._bottomBoundary) {
482             this._scrollToBottomEvent();
483             this._bottomBounceNeeded = true;
484         } else
485             this._bottomBounceNeeded = false;
486 
487         var icTopPos = locContainer.getTopBoundary();
488         if (icTopPos < this._topBoundary) {
489             this._scrollToTopEvent();
490             this._topBounceNeeded = true;
491         } else
492             this._topBounceNeeded = false;
493 
494         var icRightPos = locContainer.getRightBoundary();
495         if (icRightPos < this._rightBoundary) {
496             this._scrollToRightEvent();
497             this._rightBounceNeeded = true;
498         } else
499             this._rightBounceNeeded = false;
500 
501         var icLeftPos = locContainer.getLeftBoundary();
502         if (icLeftPos > this._leftBoundary) {
503             this._scrollToLeftEvent();
504             this._leftBounceNeeded = true;
505         } else
506             this._leftBounceNeeded = false;
507     },
508 
509     _startBounceChildren: function (v) {
510         this._bounceOriginalSpeed = v;
511         this._bouncing = true;
512     },
513 
514     _stopBounceChildren: function () {
515         this._bouncing = false;
516         this._bounceOriginalSpeed = 0.0;
517         this._leftBounceNeeded = false;
518         this._rightBounceNeeded = false;
519         this._topBounceNeeded = false;
520         this._bottomBounceNeeded = false;
521     },
522 
523     _startAutoScrollChildrenWithOriginalSpeed: function (dir, v, attenuated, acceleration) {
524         this._stopAutoScrollChildren();
525         this._autoScrollDir.x = dir.x;
526         this._autoScrollDir.y = dir.y;
527         this._isAutoScrollSpeedAttenuated = attenuated;
528         this._autoScrollOriginalSpeed = v;
529         this._autoScroll = true;
530         this._autoScrollAcceleration = acceleration;
531     },
532 
533     _startAutoScrollChildrenWithDestination: function (des, time, attenuated) {
534         this._needCheckAutoScrollDestination = false;
535         this._autoScrollDestination = des;
536         var dis = cc.pSub(des, this._innerContainer.getPosition());
537         var dir = cc.pNormalize(dis);
538         var orSpeed = 0.0;
539         var acceleration = -1000.0;
540         var disLength = cc.pLength(dis);
541         if (attenuated) {
542             acceleration = -(2 * disLength) / (time * time);
543             orSpeed = 2 * disLength / time;
544         } else {
545             this._needCheckAutoScrollDestination = true;
546             orSpeed = disLength / time;
547         }
548         this._startAutoScrollChildrenWithOriginalSpeed(dir, orSpeed, attenuated, acceleration);
549     },
550 
551     _jumpToDestination: function (dstX, dstY) {
552         if (dstX.x !== undefined) {
553             dstY = dstX.y;
554             dstX = dstX.x;
555         }
556         var finalOffsetX = dstX;
557         var finalOffsetY = dstY;
558         switch (this.direction) {
559             case ccui.ScrollView.DIR_VERTICAL:
560                 if (dstY <= 0)
561                     finalOffsetY = Math.max(dstY, this._contentSize.height - this._innerContainer.getContentSize().height);
562                 break;
563             case ccui.ScrollView.DIR_HORIZONTAL:
564                 if (dstX <= 0)
565                     finalOffsetX = Math.max(dstX, this._contentSize.width - this._innerContainer.getContentSize().width);
566                 break;
567             case ccui.ScrollView.DIR_BOTH:
568                 if (dstY <= 0)
569                     finalOffsetY = Math.max(dstY, this._contentSize.height - this._innerContainer.getContentSize().height);
570                 if (dstX <= 0)
571                     finalOffsetX = Math.max(dstX, this._contentSize.width - this._innerContainer.getContentSize().width);
572                 break;
573             default:
574                 break;
575         }
576         this._innerContainer.setPosition(finalOffsetX, finalOffsetY);
577     },
578 
579     _stopAutoScrollChildren: function () {
580         this._autoScroll = false;
581         this._autoScrollOriginalSpeed = 0;
582         this._autoScrollAddUpTime = 0;
583     },
584 
585     _bounceScrollChildren: function (touchOffsetX, touchOffsetY) {
586         var scrollEnabled = true;
587         var realOffsetX, realOffsetY, icRightPos, icTopPos, icBottomPos;
588         var locContainer = this._innerContainer;
589         if (touchOffsetX > 0.0 && touchOffsetY > 0.0){              //first quadrant //bounce to top-right
590             realOffsetX = touchOffsetX;
591             realOffsetY = touchOffsetY;
592             icRightPos = locContainer.getRightBoundary();
593             if (icRightPos + realOffsetX >= this._rightBoundary) {
594                 realOffsetX = this._rightBoundary - icRightPos;
595                 this._bounceRightEvent();
596                 scrollEnabled = false;
597             }
598             icTopPos = locContainer.getTopBoundary();
599             if (icTopPos + touchOffsetY >= this._topBoundary) {
600                 realOffsetY = this._topBoundary - icTopPos;
601                 this._bounceTopEvent();
602                 scrollEnabled = false;
603             }
604             this._moveChildren(realOffsetX, realOffsetY);
605         } else if (touchOffsetX < 0.0 && touchOffsetY > 0.0){       //second quadrant //bounce to top-left
606             realOffsetX = touchOffsetX;
607             realOffsetY = touchOffsetY;
608             icLefrPos = locContainer.getLeftBoundary();
609             if (icLefrPos + realOffsetX <= this._leftBoundary) {
610                 realOffsetX = this._leftBoundary - icLefrPos;
611                 this._bounceLeftEvent();
612                 scrollEnabled = false;
613             }
614             icTopPos = locContainer.getTopBoundary();
615             if (icTopPos + touchOffsetY >= this._topBoundary) {
616                 realOffsetY = this._topBoundary - icTopPos;
617                 this._bounceTopEvent();
618                 scrollEnabled = false;
619             }
620             this._moveChildren(realOffsetX, realOffsetY);
621         }else if (touchOffsetX < 0.0 && touchOffsetY < 0.0){ //third quadrant //bounce to bottom-left
622             realOffsetX = touchOffsetX;
623             realOffsetY = touchOffsetY;
624             var icLefrPos = locContainer.getLeftBoundary();
625             if (icLefrPos + realOffsetX <= this._leftBoundary) {
626                 realOffsetX = this._leftBoundary - icLefrPos;
627                 this._bounceLeftEvent();
628                 scrollEnabled = false;
629             }
630             icBottomPos = locContainer.getBottomBoundary();
631             if (icBottomPos + touchOffsetY <= this._bottomBoundary) {
632                 realOffsetY = this._bottomBoundary - icBottomPos;
633                 this._bounceBottomEvent();
634                 scrollEnabled = false;
635             }
636             this._moveChildren(realOffsetX, realOffsetY);
637         } else if (touchOffsetX > 0.0 && touchOffsetY < 0.0){ //forth quadrant //bounce to bottom-right
638             realOffsetX = touchOffsetX;
639             realOffsetY = touchOffsetY;
640             icRightPos = locContainer.getRightBoundary();
641             if (icRightPos + realOffsetX >= this._rightBoundary) {
642                 realOffsetX = this._rightBoundary - icRightPos;
643                 this._bounceRightEvent();
644                 scrollEnabled = false;
645             }
646             icBottomPos = locContainer.getBottomBoundary();
647             if (icBottomPos + touchOffsetY <= this._bottomBoundary) {
648                 realOffsetY = this._bottomBoundary - icBottomPos;
649                 this._bounceBottomEvent();
650                 scrollEnabled = false;
651             }
652             this._moveChildren(realOffsetX, realOffsetY);
653         } else if (touchOffsetX == 0.0 && touchOffsetY > 0.0){ // bounce to top
654             realOffsetY = touchOffsetY;
655             icTopPos = locContainer.getTopBoundary();
656             if (icTopPos + touchOffsetY >= this._topBoundary) {
657                 realOffsetY = this._topBoundary - icTopPos;
658                 this._bounceTopEvent();
659                 scrollEnabled = false;
660             }
661             this._moveChildren(0.0, realOffsetY);
662         } else if (touchOffsetX == 0.0 && touchOffsetY < 0.0) {//bounce to bottom
663             realOffsetY = touchOffsetY;
664             icBottomPos = locContainer.getBottomBoundary();
665             if (icBottomPos + touchOffsetY <= this._bottomBoundary) {
666                 realOffsetY = this._bottomBoundary - icBottomPos;
667                 this._bounceBottomEvent();
668                 scrollEnabled = false;
669             }
670             this._moveChildren(0.0, realOffsetY);
671         } else if (touchOffsetX > 0.0 && touchOffsetY == 0.0){ //bounce to right
672             realOffsetX = touchOffsetX;
673             icRightPos = locContainer.getRightBoundary();
674             if (icRightPos + realOffsetX >= this._rightBoundary) {
675                 realOffsetX = this._rightBoundary - icRightPos;
676                 this._bounceRightEvent();
677                 scrollEnabled = false;
678             }
679             this._moveChildren(realOffsetX, 0.0);
680         }else if (touchOffsetX < 0.0 && touchOffsetY == 0.0){ //bounce to left
681             realOffsetX = touchOffsetX;
682             var icLeftPos = locContainer.getLeftBoundary();
683             if (icLeftPos + realOffsetX <= this._leftBoundary) {
684                 realOffsetX = this._leftBoundary - icLeftPos;
685                 this._bounceLeftEvent();
686                 scrollEnabled = false;
687             }
688             this._moveChildren(realOffsetX, 0.0);
689         }
690         return scrollEnabled;
691     },
692 
693     _checkCustomScrollDestination: function (touchOffsetX, touchOffsetY) {
694         var scrollEnabled = true;
695         var icBottomPos, icLeftPos, icRightPos, icTopPos;
696         var locContainer = this._innerContainer, locDestination = this._autoScrollDestination;
697         switch (this.direction) {
698             case ccui.ScrollView.DIR_VERTICAL: // vertical
699                 if (this._autoScrollDir.y > 0) {
700                     icBottomPos = locContainer.getBottomBoundary();
701                     if (icBottomPos + touchOffsetY >= locDestination.y) {
702                         touchOffsetY = locDestination.y - icBottomPos;
703                         scrollEnabled = false;
704                     }
705                 } else {
706                     icBottomPos = locContainer.getBottomBoundary();
707                     if (icBottomPos + touchOffsetY <= locDestination.y) {
708                         touchOffsetY = locDestination.y - icBottomPos;
709                         scrollEnabled = false;
710                     }
711                 }
712                 break;
713             case ccui.ScrollView.DIR_HORIZONTAL: // horizontal
714                 if (this._autoScrollDir.x > 0) {
715                     icLeftPos = locContainer.getLeftBoundary();
716                     if (icLeftPos + touchOffsetX >= locDestination.x) {
717                         touchOffsetX = locDestination.x - icLeftPos;
718                         scrollEnabled = false;
719                     }
720                 } else {
721                     icLeftPos = locContainer.getLeftBoundary();
722                     if (icLeftPos + touchOffsetX <= locDestination.x) {
723                         touchOffsetX = locDestination.x - icLeftPos;
724                         scrollEnabled = false;
725                     }
726                 }
727                 break;
728             case ccui.ScrollView.DIR_BOTH:
729                 if (touchOffsetX > 0.0 && touchOffsetY > 0.0){ // up right
730                     icLeftPos = locContainer.getLeftBoundary();
731                     if (icLeftPos + touchOffsetX >= locDestination.x) {
732                         touchOffsetX = locDestination.x - icLeftPos;
733                         scrollEnabled = false;
734                     }
735                     icBottomPos = locContainer.getBottomBoundary();
736                     if (icBottomPos + touchOffsetY >= locDestination.y) {
737                         touchOffsetY = locDestination.y - icBottomPos;
738                         scrollEnabled = false;
739                     }
740                 } else if (touchOffsetX < 0.0 && touchOffsetY > 0.0){ // up left
741                     icRightPos = locContainer.getRightBoundary();
742                     if (icRightPos + touchOffsetX <= locDestination.x) {
743                         touchOffsetX = locDestination.x - icRightPos;
744                         scrollEnabled = false;
745                     }
746                     icBottomPos = locContainer.getBottomBoundary();
747                     if (icBottomPos + touchOffsetY >= locDestination.y) {
748                         touchOffsetY = locDestination.y - icBottomPos;
749                         scrollEnabled = false;
750                     }
751                 } else if (touchOffsetX < 0.0 && touchOffsetY < 0.0){ // down left
752                     icRightPos = locContainer.getRightBoundary();
753                     if (icRightPos + touchOffsetX <= locDestination.x) {
754                         touchOffsetX = locDestination.x - icRightPos;
755                         scrollEnabled = false;
756                     }
757                     icTopPos = locContainer.getTopBoundary();
758                     if (icTopPos + touchOffsetY <= locDestination.y) {
759                         touchOffsetY = locDestination.y - icTopPos;
760                         scrollEnabled = false;
761                     }
762                 } else if (touchOffsetX > 0.0 && touchOffsetY < 0.0){ // down right
763                     icLeftPos = locContainer.getLeftBoundary();
764                     if (icLeftPos + touchOffsetX >= locDestination.x) {
765                         touchOffsetX = locDestination.x - icLeftPos;
766                         scrollEnabled = false;
767                     }
768                     icTopPos = locContainer.getTopBoundary();
769                     if (icTopPos + touchOffsetY <= locDestination.y) {
770                         touchOffsetY = locDestination.y - icTopPos;
771                         scrollEnabled = false;
772                     }
773                 } else if (touchOffsetX == 0.0 && touchOffsetY > 0.0){ // up
774                     icBottomPos = locContainer.getBottomBoundary();
775                     if (icBottomPos + touchOffsetY >= locDestination.y) {
776                         touchOffsetY = locDestination.y - icBottomPos;
777                         scrollEnabled = false;
778                     }
779                 } else if (touchOffsetX < 0.0 && touchOffsetY == 0.0){ // left
780                     icRightPos = locContainer.getRightBoundary();
781                     if (icRightPos + touchOffsetX <= locDestination.x) {
782                         touchOffsetX = locDestination.x - icRightPos;
783                         scrollEnabled = false;
784                     }
785                 } else if (touchOffsetX == 0.0 && touchOffsetY < 0.0){ // down
786                     icTopPos = locContainer.getTopBoundary();
787                     if (icTopPos + touchOffsetY <= locDestination.y) {
788                         touchOffsetY = locDestination.y - icTopPos;
789                         scrollEnabled = false;
790                     }
791                 } else if (touchOffsetX > 0.0 && touchOffsetY == 0.0){ // right
792                     icLeftPos = locContainer.getLeftBoundary();
793                     if (icLeftPos + touchOffsetX >= locDestination.x) {
794                         touchOffsetX = locDestination.x - icLeftPos;
795                         scrollEnabled = false;
796                     }
797                 }
798                 break;
799             default:
800                 break;
801         }
802         return scrollEnabled;
803     },
804 
805     _scrollChildren: function (touchOffsetX, touchOffsetY) {
806         var scrollEnabled = true;
807         this._scrollingEvent();
808         switch (this.direction) {
809             case ccui.ScrollView.DIR_VERTICAL: // vertical
810                 scrollEnabled = this._scrollChildrenVertical(touchOffsetX, touchOffsetY);
811                 break;
812             case ccui.ScrollView.DIR_HORIZONTAL: // horizontal
813                 scrollEnabled = this._scrollChildrenHorizontal(touchOffsetX, touchOffsetY);
814                 break;
815             case ccui.ScrollView.DIR_BOTH:
816                 scrollEnabled = this._scrollChildrenBoth(touchOffsetX, touchOffsetY);
817                 break;
818             default:
819                 break;
820         }
821         return scrollEnabled;
822     },
823 
824     _scrollChildrenVertical: function(touchOffsetX, touchOffsetY){
825         var realOffset = touchOffsetY;
826         var scrollEnabled = true;
827         var icBottomPos, icTopPos, locContainer = this._innerContainer;
828         if (this.bounceEnabled) {
829             icBottomPos = locContainer.getBottomBoundary();
830             if (icBottomPos + touchOffsetY >= this._bounceBottomBoundary) {
831                 realOffset = this._bounceBottomBoundary - icBottomPos;
832                 this._scrollToBottomEvent();
833                 scrollEnabled = false;
834             }
835             icTopPos = locContainer.getTopBoundary();
836             if (icTopPos + touchOffsetY <= this._bounceTopBoundary) {
837                 realOffset = this._bounceTopBoundary - icTopPos;
838                 this._scrollToTopEvent();
839                 scrollEnabled = false;
840 
841             }
842         } else {
843             icBottomPos = locContainer.getBottomBoundary();
844             if (icBottomPos + touchOffsetY >= this._bottomBoundary){
845                 realOffset = this._bottomBoundary - icBottomPos;
846                 this._scrollToBottomEvent();
847                 scrollEnabled = false;
848             }
849             icTopPos = locContainer.getTopBoundary();
850             if (icTopPos + touchOffsetY <= this._topBoundary) {
851                 realOffset = this._topBoundary - icTopPos;
852                 this._scrollToTopEvent();
853                 scrollEnabled = false;
854             }
855         }
856         this._moveChildren(0.0, realOffset);
857         return scrollEnabled;
858     },
859 
860     _scrollChildrenHorizontal: function(touchOffsetX, touchOffestY){
861         var scrollEnabled = true;
862         var realOffset = touchOffsetX;
863         var icRightPos, icLeftPos, locContainer = this._innerContainer;
864         if (this.bounceEnabled){
865             icRightPos = locContainer.getRightBoundary();
866             if (icRightPos + touchOffsetX <= this._bounceRightBoundary) {
867                 realOffset = this._bounceRightBoundary - icRightPos;
868                 this._scrollToRightEvent();
869                 scrollEnabled = false;
870             }
871             icLeftPos = locContainer.getLeftBoundary();
872             if (icLeftPos + touchOffsetX >= this._bounceLeftBoundary) {
873                 realOffset = this._bounceLeftBoundary - icLeftPos;
874                 this._scrollToLeftEvent();
875                 scrollEnabled = false;
876             }
877         } else {
878             icRightPos = locContainer.getRightBoundary();
879             if (icRightPos + touchOffsetX <= this._rightBoundary) {
880                 realOffset = this._rightBoundary - icRightPos;
881                 this._scrollToRightEvent();
882                 scrollEnabled = false;
883             }
884             icLeftPos = locContainer.getLeftBoundary();
885             if (icLeftPos + touchOffsetX >= this._leftBoundary) {
886                 realOffset = this._leftBoundary - icLeftPos;
887                 this._scrollToLeftEvent();
888                 scrollEnabled = false;
889             }
890         }
891         this._moveChildren(realOffset, 0.0);
892         return scrollEnabled;
893     },
894 
895     _scrollChildrenBoth: function (touchOffsetX, touchOffsetY) {
896         var scrollEnabled = true;
897         var realOffsetX = touchOffsetX;
898         var realOffsetY = touchOffsetY;
899         var icLeftPos, icBottomPos, icRightPos, icTopPos;
900         var locContainer = this._innerContainer;
901         if (this.bounceEnabled) {
902             if (touchOffsetX > 0.0 && touchOffsetY > 0.0) { // up right
903                 icLeftPos = locContainer.getLeftBoundary();
904                 if (icLeftPos + touchOffsetX >= this._bounceLeftBoundary) {
905                     realOffsetX = this._bounceLeftBoundary - icLeftPos;
906                     this._scrollToLeftEvent();
907                     scrollEnabled = false;
908                 }
909                 icBottomPos = locContainer.getBottomBoundary();
910                 if (icBottomPos + touchOffsetY >= this._bounceBottomBoundary) {
911                     realOffsetY = this._bounceBottomBoundary - icBottomPos;
912                     this._scrollToBottomEvent();
913                     scrollEnabled = false;
914                 }
915             } else if (touchOffsetX < 0.0 && touchOffsetY > 0.0) { // up left
916                 icRightPos = locContainer.getRightBoundary();
917                 if (icRightPos + touchOffsetX <= this._bounceRightBoundary) {
918                     realOffsetX = this._bounceRightBoundary - icRightPos;
919                     this._scrollToRightEvent();
920                     scrollEnabled = false;
921                 }
922                 icBottomPos = locContainer.getBottomBoundary();
923                 if (icBottomPos + touchOffsetY >= this._bounceBottomBoundary) {
924                     realOffsetY = this._bounceBottomBoundary - icBottomPos;
925                     this._scrollToBottomEvent();
926                     scrollEnabled = false;
927                 }
928             } else if (touchOffsetX < 0.0 && touchOffsetY < 0.0) { // down left
929                 icRightPos = locContainer.getRightBoundary();
930                 if (icRightPos + touchOffsetX <= this._bounceRightBoundary) {
931                     realOffsetX = this._bounceRightBoundary - icRightPos;
932                     this._scrollToRightEvent();
933                     scrollEnabled = false;
934                 }
935                 icTopPos = locContainer.getTopBoundary();
936                 if (icTopPos + touchOffsetY <= this._bounceTopBoundary) {
937                     realOffsetY = this._bounceTopBoundary - icTopPos;
938                     this._scrollToTopEvent();
939                     scrollEnabled = false;
940                 }
941             } else if (touchOffsetX > 0.0 && touchOffsetY < 0.0){ // down right
942                 icLeftPos = locContainer.getLeftBoundary();
943                 if (icLeftPos + touchOffsetX >= this._bounceLeftBoundary) {
944                     realOffsetX = this._bounceLeftBoundary - icLeftPos;
945                     this._scrollToLeftEvent();
946                     scrollEnabled = false;
947                 }
948                 icTopPos = locContainer.getTopBoundary();
949                 if (icTopPos + touchOffsetY <= this._bounceTopBoundary) {
950                     realOffsetY = this._bounceTopBoundary - icTopPos;
951                     this._scrollToTopEvent();
952                     scrollEnabled = false;
953                 }
954             } else if (touchOffsetX == 0.0 && touchOffsetY > 0.0){ // up
955                 icBottomPos = locContainer.getBottomBoundary();
956                 if (icBottomPos + touchOffsetY >= this._bounceBottomBoundary) {
957                     realOffsetY = this._bounceBottomBoundary - icBottomPos;
958                     this._scrollToBottomEvent();
959                     scrollEnabled = false;
960                 }
961             } else if (touchOffsetX < 0.0 && touchOffsetY == 0.0){ // left
962                 icRightPos = locContainer.getRightBoundary();
963                 if (icRightPos + touchOffsetX <= this._bounceRightBoundary) {
964                     realOffsetX = this._bounceRightBoundary - icRightPos;
965                     this._scrollToRightEvent();
966                     scrollEnabled = false;
967                 }
968             } else if (touchOffsetX == 0.0 && touchOffsetY < 0.0){ // down
969                 icTopPos = locContainer.getTopBoundary();
970                 if (icTopPos + touchOffsetY <= this._bounceTopBoundary) {
971                     realOffsetY = this._bounceTopBoundary - icTopPos;
972                     this._scrollToTopEvent();
973                     scrollEnabled = false;
974                 }
975             } else if (touchOffsetX > 0.0 && touchOffsetY == 0.0){ // right
976                 icLeftPos = locContainer.getLeftBoundary();
977                 if (icLeftPos + touchOffsetX >= this._bounceLeftBoundary) {
978                     realOffsetX = this._bounceLeftBoundary - icLeftPos;
979                     this._scrollToLeftEvent();
980                     scrollEnabled = false;
981                 }
982             }
983         } else {
984             if (touchOffsetX > 0.0 && touchOffsetY > 0.0){ // up right
985                 icLeftPos = locContainer.getLeftBoundary();
986                 if (icLeftPos + touchOffsetX >= this._leftBoundary) {
987                     realOffsetX = this._leftBoundary - icLeftPos;
988                     this._scrollToLeftEvent();
989                     scrollEnabled = false;
990                 }
991                 icBottomPos = locContainer.getBottomBoundary();
992                 if (icBottomPos + touchOffsetY >= this._bottomBoundary) {
993                     realOffsetY = this._bottomBoundary - icBottomPos;
994                     this._scrollToBottomEvent();
995                     scrollEnabled = false;
996                 }
997             } else if (touchOffsetX < 0.0 && touchOffsetY > 0.0){ // up left
998                 icRightPos = locContainer.getRightBoundary();
999                 if (icRightPos + touchOffsetX <= this._rightBoundary) {
1000                     realOffsetX = this._rightBoundary - icRightPos;
1001                     this._scrollToRightEvent();
1002                     scrollEnabled = false;
1003                 }
1004                 icBottomPos = locContainer.getBottomBoundary();
1005                 if (icBottomPos + touchOffsetY >= this._bottomBoundary) {
1006                     realOffsetY = this._bottomBoundary - icBottomPos;
1007                     this._scrollToBottomEvent();
1008                     scrollEnabled = false;
1009                 }
1010             } else if (touchOffsetX < 0.0 && touchOffsetY < 0.0){ // down left
1011                 icRightPos = locContainer.getRightBoundary();
1012                 if (icRightPos + touchOffsetX <= this._rightBoundary) {
1013                     realOffsetX = this._rightBoundary - icRightPos;
1014                     this._scrollToRightEvent();
1015                     scrollEnabled = false;
1016                 }
1017                 icTopPos = locContainer.getTopBoundary();
1018                 if (icTopPos + touchOffsetY <= this._topBoundary) {
1019                     realOffsetY = this._topBoundary - icTopPos;
1020                     this._scrollToTopEvent();
1021                     scrollEnabled = false;
1022                 }
1023             } else if (touchOffsetX > 0.0 && touchOffsetY < 0.0){ // down right
1024                 icLeftPos = locContainer.getLeftBoundary();
1025                 if (icLeftPos + touchOffsetX >= this._leftBoundary) {
1026                     realOffsetX = this._leftBoundary - icLeftPos;
1027                     this._scrollToLeftEvent();
1028                     scrollEnabled = false;
1029                 }
1030                 icTopPos = this._innerContainer.getTopBoundary();
1031                 if (icTopPos + touchOffsetY <= this._topBoundary) {
1032                     realOffsetY = this._topBoundary - icTopPos;
1033                     this._scrollToTopEvent();
1034                     scrollEnabled = false;
1035                 }
1036             } else if (touchOffsetX == 0.0 && touchOffsetY > 0.0) { // up
1037                 icBottomPos = this._innerContainer.getBottomBoundary();
1038                 if (icBottomPos + touchOffsetY >= this._bottomBoundary) {
1039                     realOffsetY = this._bottomBoundary - icBottomPos;
1040                     this._scrollToBottomEvent();
1041                     scrollEnabled = false;
1042                 }
1043             } else if (touchOffsetX < 0.0 && touchOffsetY == 0.0){ // left
1044                 icRightPos = this._innerContainer.getRightBoundary();
1045                 if (icRightPos + touchOffsetX <= this._rightBoundary) {
1046                     realOffsetX = this._rightBoundary - icRightPos;
1047                     this._scrollToRightEvent();
1048                     scrollEnabled = false;
1049                 }
1050             } else if (touchOffsetX == 0.0 && touchOffsetY < 0.0){  // down
1051                 icTopPos = this._innerContainer.getTopBoundary();
1052                 if (icTopPos + touchOffsetY <= this._topBoundary) {
1053                     realOffsetY = this._topBoundary - icTopPos;
1054                     this._scrollToTopEvent();
1055                     scrollEnabled = false;
1056                 }
1057             }  else if (touchOffsetX > 0.0 && touchOffsetY == 0.0){ // right
1058                 icLeftPos = this._innerContainer.getLeftBoundary();
1059                 if (icLeftPos + touchOffsetX >= this._leftBoundary) {
1060                     realOffsetX = this._leftBoundary - icLeftPos;
1061                     this._scrollToLeftEvent();
1062                     scrollEnabled = false;
1063                 }
1064             }
1065         }
1066         this._moveChildren(realOffsetX, realOffsetY);
1067         return scrollEnabled;
1068     },
1069 
1070     /**
1071      * Scroll inner container to bottom boundary of ScrollView.
1072      * @param {Number} time
1073      * @param {Boolean} attenuated
1074      */
1075     scrollToBottom: function (time, attenuated) {
1076         this._startAutoScrollChildrenWithDestination(cc.p(this._innerContainer.getPositionX(), 0), time, attenuated);
1077     },
1078 
1079     /**
1080      * Scroll inner container to top boundary of ScrollView.
1081      * @param {Number} time
1082      * @param {Boolean} attenuated
1083      */
1084     scrollToTop: function (time, attenuated) {
1085         this._startAutoScrollChildrenWithDestination(
1086             cc.p(this._innerContainer.getPositionX(), this._contentSize.height - this._innerContainer.getContentSize().height), time, attenuated);
1087     },
1088 
1089     /**
1090      * Scroll inner container to left boundary of ScrollView.
1091      * @param {Number} time
1092      * @param {Boolean} attenuated
1093      */
1094     scrollToLeft: function (time, attenuated) {
1095         this._startAutoScrollChildrenWithDestination(cc.p(0, this._innerContainer.getPositionY()), time, attenuated);
1096     },
1097 
1098     /**
1099      * Scroll inner container to right boundary of ScrollView.
1100      * @param {Number} time
1101      * @param {Boolean} attenuated
1102      */
1103     scrollToRight: function (time, attenuated) {
1104         this._startAutoScrollChildrenWithDestination(
1105             cc.p(this._contentSize.width - this._innerContainer.getContentSize().width, this._innerContainer.getPositionY()), time, attenuated);
1106     },
1107 
1108     /**
1109      * Scroll inner container to top and left boundary of ScrollView.
1110      * @param {Number} time
1111      * @param {Boolean} attenuated
1112      */
1113     scrollToTopLeft: function (time, attenuated) {
1114         if (this.direction != ccui.ScrollView.DIR_BOTH) {
1115             cc.log("Scroll direction is not both!");
1116             return;
1117         }
1118         this._startAutoScrollChildrenWithDestination(cc.p(0, this._contentSize.height - this._innerContainer.getContentSize().height), time, attenuated);
1119     },
1120 
1121     /**
1122      * Scroll inner container to top and right boundary of ScrollView.
1123      * @param {Number} time
1124      * @param {Boolean} attenuated
1125      */
1126     scrollToTopRight: function (time, attenuated) {
1127         if (this.direction != ccui.ScrollView.DIR_BOTH) {
1128             cc.log("Scroll direction is not both!");
1129             return;
1130         }
1131         var inSize = this._innerContainer.getContentSize();
1132         this._startAutoScrollChildrenWithDestination(cc.p(this._contentSize.width - inSize.width,
1133                 this._contentSize.height - inSize.height), time, attenuated);
1134     },
1135 
1136     /**
1137      * Scroll inner container to bottom and left boundary of ScrollView.
1138      * @param {Number} time
1139      * @param {Boolean} attenuated
1140      */
1141     scrollToBottomLeft: function (time, attenuated) {
1142         if (this.direction != ccui.ScrollView.DIR_BOTH) {
1143             cc.log("Scroll direction is not both!");
1144             return;
1145         }
1146         this._startAutoScrollChildrenWithDestination(cc.p(0, 0), time, attenuated);
1147     },
1148 
1149     /**
1150      * Scroll inner container to bottom and right boundary of ScrollView.
1151      * @param {Number} time
1152      * @param {Boolean} attenuated
1153      */
1154     scrollToBottomRight: function (time, attenuated) {
1155         if (this.direction != ccui.ScrollView.DIR_BOTH) {
1156             cc.log("Scroll direction is not both!");
1157             return;
1158         }
1159         this._startAutoScrollChildrenWithDestination(cc.p(this._contentSize.width - this._innerContainer.getContentSize().width, 0), time, attenuated);
1160     },
1161 
1162     /**
1163      * Scroll inner container to vertical percent position of ScrollView.
1164      * @param {Number} percent
1165      * @param {Number} time
1166      * @param {Boolean} attenuated
1167      */
1168     scrollToPercentVertical: function (percent, time, attenuated) {
1169         var minY = this._contentSize.height - this._innerContainer.getContentSize().height;
1170         var h = -minY;
1171         this._startAutoScrollChildrenWithDestination(cc.p(this._innerContainer.getPositionX(), minY + percent * h / 100), time, attenuated);
1172     },
1173 
1174     /**
1175      * Scroll inner container to horizontal percent position of ScrollView.
1176      * @param {Number} percent
1177      * @param {Number} time
1178      * @param {Boolean} attenuated
1179      */
1180     scrollToPercentHorizontal: function (percent, time, attenuated) {
1181         var w = this._innerContainer.getContentSize().width - this._contentSize.width;
1182         this._startAutoScrollChildrenWithDestination(cc.p(-(percent * w / 100), this._innerContainer.getPositionY()), time, attenuated);
1183     },
1184 
1185     /**
1186      * Scroll inner container to both direction percent position of ScrollView.
1187      * @param {cc.Point} percent
1188      * @param {Number} time
1189      * @param {Boolean} attenuated
1190      */
1191     scrollToPercentBothDirection: function (percent, time, attenuated) {
1192         if (this.direction != ccui.ScrollView.DIR_BOTH)
1193             return;
1194         var minY = this._contentSize.height - this._innerContainer.getContentSize().height;
1195         var h = -minY;
1196         var w = this._innerContainer.getContentSize().width - this._contentSize.width;
1197         this._startAutoScrollChildrenWithDestination(cc.p(-(percent.x * w / 100), minY + percent.y * h / 100), time, attenuated);
1198     },
1199 
1200     /**
1201      * Move inner container to bottom boundary of ScrollView.
1202      */
1203     jumpToBottom: function () {
1204         this._jumpToDestination(this._innerContainer.getPositionX(), 0);
1205     },
1206 
1207     /**
1208      * Move inner container to top boundary of ScrollView.
1209      */
1210     jumpToTop: function () {
1211         this._jumpToDestination(this._innerContainer.getPositionX(), this._contentSize.height - this._innerContainer.getContentSize().height);
1212     },
1213 
1214     /**
1215      * Move inner container to left boundary of ScrollView.
1216      */
1217     jumpToLeft: function () {
1218         this._jumpToDestination(0, this._innerContainer.getPositionY());
1219     },
1220 
1221     /**
1222      * Move inner container to right boundary of ScrollView.
1223      */
1224     jumpToRight: function () {
1225         this._jumpToDestination(this._contentSize.width - this._innerContainer.getContentSize().width, this._innerContainer.getPositionY());
1226     },
1227 
1228     /**
1229      * Move inner container to top and left boundary of ScrollView.
1230      */
1231     jumpToTopLeft: function () {
1232         if (this.direction != ccui.ScrollView.DIR_BOTH) {
1233             cc.log("Scroll direction is not both!");
1234             return;
1235         }
1236         this._jumpToDestination(0, this._contentSize.height - this._innerContainer.getContentSize().height);
1237     },
1238 
1239     /**
1240      * Move inner container to top and right boundary of ScrollView.
1241      */
1242     jumpToTopRight: function () {
1243         if (this.direction != ccui.ScrollView.DIR_BOTH) {
1244             cc.log("Scroll direction is not both!");
1245             return;
1246         }
1247         var inSize = this._innerContainer.getContentSize();
1248         this._jumpToDestination(this._contentSize.width - inSize.width, this._contentSize.height - inSize.height);
1249     },
1250 
1251     /**
1252      * Move inner container to bottom and left boundary of ScrollView.
1253      */
1254     jumpToBottomLeft: function () {
1255         if (this.direction != ccui.ScrollView.DIR_BOTH) {
1256             cc.log("Scroll direction is not both!");
1257             return;
1258         }
1259         this._jumpToDestination(0, 0);
1260     },
1261 
1262     /**
1263      * Move inner container to bottom and right boundary of ScrollView.
1264      */
1265     jumpToBottomRight: function () {
1266         if (this.direction != ccui.ScrollView.DIR_BOTH) {
1267             cc.log("Scroll direction is not both!");
1268             return;
1269         }
1270         this._jumpToDestination(this._contentSize.width - this._innerContainer.getContentSize().width, 0);
1271     },
1272 
1273     /**
1274      * Move inner container to vertical percent position of ScrollView.
1275      * @param {Number} percent The destination vertical percent, accept value between 0 - 100
1276      */
1277     jumpToPercentVertical: function (percent) {
1278         var minY = this._contentSize.height - this._innerContainer.getContentSize().height;
1279         var h = -minY;
1280         this._jumpToDestination(this._innerContainer.getPositionX(), minY + percent * h / 100);
1281     },
1282 
1283     /**
1284      * Move inner container to horizontal percent position of ScrollView.
1285      * @param {Number} percent The destination vertical percent, accept value between 0 - 100
1286      */
1287     jumpToPercentHorizontal: function (percent) {
1288         var w = this._innerContainer.getContentSize().width - this._contentSize.width;
1289         this._jumpToDestination(-(percent * w / 100), this._innerContainer.getPositionY());
1290     },
1291 
1292     /**
1293      * Move inner container to both direction percent position of ScrollView.
1294      * @param {cc.Point} percent The destination vertical percent, accept value between 0 - 100
1295      */
1296     jumpToPercentBothDirection: function (percent) {
1297         if (this.direction != ccui.ScrollView.DIR_BOTH)
1298             return;
1299         var inSize = this._innerContainer.getContentSize();
1300         var minY = this._contentSize.height - inSize.height;
1301         var h = -minY;
1302         var w = inSize.width - this._contentSize.width;
1303         this._jumpToDestination(-(percent.x * w / 100), minY + percent.y * h / 100);
1304     },
1305 
1306     _startRecordSlidAction: function () {
1307         if (this._autoScroll)
1308             this._stopAutoScrollChildren();
1309         if (this._bouncing)
1310             this._stopBounceChildren();
1311         this._slidTime = 0.0;
1312     },
1313 
1314     _endRecordSlidAction: function () {
1315         if (!this._checkNeedBounce() && this.inertiaScrollEnabled) {
1316             if (this._slidTime <= 0.016)
1317                 return;
1318             var totalDis = 0;
1319             var dir;
1320             switch (this.direction) {
1321                 case ccui.ScrollView.DIR_VERTICAL :
1322                     totalDis = this._touchEndPosition.y - this._touchBeganPosition.y;
1323                     dir = (totalDis < 0) ? ccui.ScrollView.SCROLLDIR_DOWN : ccui.ScrollView.SCROLLDIR_UP;
1324                     break;
1325                 case ccui.ScrollView.DIR_HORIZONTAL:
1326                     totalDis = this._touchEndPosition.x - this._touchBeganPosition.x;
1327                     dir = totalDis < 0 ? ccui.ScrollView.SCROLLDIR_LEFT : ccui.ScrollView.SCROLLDIR_RIGHT;
1328                     break;
1329                 case ccui.ScrollView.DIR_BOTH :
1330                     var subVector = cc.pSub(this._touchEndPosition, this._touchBeganPosition);
1331                     totalDis = cc.pLength(subVector);
1332                     dir = cc.pNormalize(subVector);
1333                     break;
1334                 default:
1335                     break;
1336             }
1337             var orSpeed = Math.min(Math.abs(totalDis) / (this._slidTime), ccui.ScrollView.AUTO_SCROLL_MAX_SPEED);
1338             this._startAutoScrollChildrenWithOriginalSpeed(dir, orSpeed, true, -1000);
1339             this._slidTime = 0;
1340         }
1341     },
1342 
1343     _handlePressLogic: function (touch) {
1344         this._startRecordSlidAction();
1345         this._bePressed = true;
1346     },
1347 
1348     _handleMoveLogic: function (touch) {
1349         var delta = cc.pSub(touch.getLocation(), touch.getPreviousLocation());
1350         switch (this.direction) {
1351             case ccui.ScrollView.DIR_VERTICAL: // vertical
1352                 this._scrollChildren(0.0, delta.y);
1353                 break;
1354             case ccui.ScrollView.DIR_HORIZONTAL: // horizontal
1355                 this._scrollChildren(delta.x, 0);
1356                 break;
1357             case ccui.ScrollView.DIR_BOTH: // both
1358                 this._scrollChildren(delta.x, delta.y);
1359                 break;
1360             default:
1361                 break;
1362         }
1363     },
1364 
1365     _handleReleaseLogic: function (touch) {
1366         this._endRecordSlidAction();
1367         this._bePressed = false;
1368     },
1369 
1370     /**
1371      * The touch began event callback handler of ccui.ScrollView.
1372      * @param {cc.Touch} touch
1373      * @param {cc.Event} event
1374      * @returns {boolean}
1375      */
1376     onTouchBegan: function (touch, event) {
1377         var pass = ccui.Layout.prototype.onTouchBegan.call(this, touch, event);
1378         if (this._hit)
1379             this._handlePressLogic(touch);
1380         return pass;
1381     },
1382 
1383     /**
1384      * The touch moved event callback handler of ccui.ScrollView.
1385      * @param {cc.Touch} touch
1386      * @param {cc.Event} event
1387      */
1388     onTouchMoved: function (touch, event) {
1389         ccui.Layout.prototype.onTouchMoved.call(this, touch, event);
1390         this._handleMoveLogic(touch);
1391     },
1392 
1393     /**
1394      * The touch ended event callback handler of ccui.ScrollView.
1395      * @param {cc.Touch} touch
1396      * @param {cc.Event} event
1397      */
1398     onTouchEnded: function (touch, event) {
1399         ccui.Layout.prototype.onTouchEnded.call(this, touch, event);
1400         this._handleReleaseLogic(touch);
1401     },
1402 
1403     /**
1404      * The touch canceled event callback of ccui.ScrollView.
1405      * @param {cc.Touch} touch
1406      * @param {cc.Event} event
1407      */
1408     onTouchCancelled: function (touch, event) {
1409         ccui.Layout.prototype.onTouchCancelled.call(this, touch, event);
1410     },
1411 
1412     /**
1413      * The update callback handler.
1414      * @param {Number} dt
1415      */
1416     update: function (dt) {
1417         if (this._autoScroll)
1418             this._autoScrollChildren(dt);
1419         if (this._bouncing)
1420             this._bounceChildren(dt);
1421         this._recordSlidTime(dt);
1422     },
1423 
1424     _recordSlidTime: function (dt) {
1425         if (this._bePressed)
1426             this._slidTime += dt;
1427     },
1428 
1429     /**
1430      * Intercept touch event, handle its child's touch event.
1431      * @override
1432      * @param {number} event event type
1433      * @param {ccui.Widget} sender
1434      * @param {cc.Touch} touch
1435      */
1436     interceptTouchEvent: function (event, sender, touch) {
1437         var touchPoint = touch.getLocation();
1438         switch (event) {
1439             case ccui.Widget.TOUCH_BEGAN:
1440                 this._touchBeganPosition.x = touchPoint.x;
1441                 this._touchBeganPosition.y = touchPoint.y;
1442                 this._handlePressLogic(touch);
1443                 break;
1444             case ccui.Widget.TOUCH_MOVED:
1445                 var offset = cc.pLength(cc.pSub(sender.getTouchBeganPosition(), touchPoint));
1446                 if (offset > this._childFocusCancelOffset) {
1447                     sender.setHighlighted(false);
1448                     this._touchMovePosition.x = touchPoint.x;
1449                     this._touchMovePosition.y = touchPoint.y;
1450                     this._handleMoveLogic(touch);
1451                 }
1452                 break;
1453             case ccui.Widget.TOUCH_CANCELED:
1454             case ccui.Widget.TOUCH_ENDED:
1455                 this._touchEndPosition.x = touchPoint.x;
1456                 this._touchEndPosition.y = touchPoint.y;
1457                 this._handleReleaseLogic(touch);
1458                 break;
1459         }
1460     },
1461 
1462     _scrollToTopEvent: function () {
1463         if(this._scrollViewEventSelector){
1464             if (this._scrollViewEventListener)
1465                 this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccui.ScrollView.EVENT_SCROLL_TO_TOP);
1466             else
1467                 this._scrollViewEventSelector(this, ccui.ScrollView.EVENT_SCROLL_TO_TOP);
1468         }
1469     },
1470 
1471     _scrollToBottomEvent: function () {
1472         if(this._scrollViewEventSelector){
1473             if (this._scrollViewEventListener)
1474                 this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccui.ScrollView.EVENT_SCROLL_TO_BOTTOM);
1475             else
1476                 this._scrollViewEventSelector(this, ccui.ScrollView.EVENT_SCROLL_TO_BOTTOM);
1477         }
1478     },
1479 
1480     _scrollToLeftEvent: function () {
1481         if(this._scrollViewEventSelector){
1482             if (this._scrollViewEventListener)
1483                 this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccui.ScrollView.EVENT_SCROLL_TO_LEFT);
1484             else
1485                 this._scrollViewEventSelector(this, ccui.ScrollView.EVENT_SCROLL_TO_LEFT);
1486         }
1487     },
1488 
1489     _scrollToRightEvent: function () {
1490         if(this._scrollViewEventSelector){
1491             if (this._scrollViewEventListener)
1492                 this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccui.ScrollView.EVENT_SCROLL_TO_RIGHT);
1493             else
1494                 this._scrollViewEventSelector(this, ccui.ScrollView.EVENT_SCROLL_TO_RIGHT);
1495         }
1496     },
1497 
1498     _scrollingEvent: function () {
1499         if(this._scrollViewEventSelector){
1500             if (this._scrollViewEventListener)
1501                 this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccui.ScrollView.EVENT_SCROLLING);
1502             else
1503                 this._scrollViewEventSelector(this, ccui.ScrollView.EVENT_SCROLLING);
1504         }
1505     },
1506 
1507     _bounceTopEvent: function () {
1508         if(this._scrollViewEventSelector){
1509             if (this._scrollViewEventListener)
1510                 this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccui.ScrollView.EVENT_BOUNCE_TOP);
1511             else
1512                 this._scrollViewEventSelector(this, ccui.ScrollView.EVENT_BOUNCE_TOP);
1513         }
1514     },
1515 
1516     _bounceBottomEvent: function () {
1517         if(this._scrollViewEventSelector){
1518             if (this._scrollViewEventListener)
1519                 this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccui.ScrollView.EVENT_BOUNCE_BOTTOM);
1520             else
1521                 this._scrollViewEventSelector(this, ccui.ScrollView.EVENT_BOUNCE_BOTTOM);
1522         }
1523     },
1524 
1525     _bounceLeftEvent: function () {
1526         if(this._scrollViewEventSelector){
1527             if (this._scrollViewEventListener)
1528                 this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccui.ScrollView.EVENT_BOUNCE_LEFT);
1529             else
1530                 this._scrollViewEventSelector(this, ccui.ScrollView.EVENT_BOUNCE_LEFT);
1531         }
1532     },
1533 
1534     _bounceRightEvent: function () {
1535         if(this._scrollViewEventSelector){
1536             if (this._scrollViewEventListener)
1537                 this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccui.ScrollView.EVENT_BOUNCE_RIGHT);
1538             else
1539                 this._scrollViewEventSelector(this, ccui.ScrollView.EVENT_BOUNCE_RIGHT);
1540         }
1541     },
1542 
1543     /**
1544      * Adds callback function called ScrollView event triggered
1545      * @param {Function} selector
1546      * @param {Object} [target=]
1547      * @deprecated since v3.0, please use addEventListener instead.
1548      */
1549     addEventListenerScrollView: function (selector, target) {
1550         this.addEventListener(selector, target);
1551     },
1552 
1553     /**
1554      * Adds callback function called ScrollView event triggered
1555      * @param {Function} selector
1556      * @param {Object} [target=]
1557      */
1558     addEventListener: function(selector, target){
1559         this._scrollViewEventSelector = selector;
1560         this._scrollViewEventListener = target;
1561     },
1562 
1563     /**
1564      * Changes scroll direction of ScrollView.
1565      * @param {ccui.ScrollView.DIR_NONE | ccui.ScrollView.DIR_VERTICAL | ccui.ScrollView.DIR_HORIZONTAL | ccui.ScrollView.DIR_BOTH} dir
1566      *   Direction::VERTICAL means vertical scroll, Direction::HORIZONTAL means horizontal scroll
1567      */
1568     setDirection: function (dir) {
1569         this.direction = dir;
1570     },
1571 
1572     /**
1573      * Returns scroll direction of ScrollView.
1574      * @returns {ccui.ScrollView.DIR_NONE | ccui.ScrollView.DIR_VERTICAL | ccui.ScrollView.DIR_HORIZONTAL | ccui.ScrollView.DIR_BOTH}
1575      */
1576     getDirection: function () {
1577         return this.direction;
1578     },
1579 
1580     /**
1581      * Sets bounce enabled
1582      * @param {Boolean} enabled
1583      */
1584     setBounceEnabled: function (enabled) {
1585         this.bounceEnabled = enabled;
1586     },
1587 
1588     /**
1589      * Returns whether bounce is enabled
1590      * @returns {boolean}
1591      */
1592     isBounceEnabled: function () {
1593         return this.bounceEnabled;
1594     },
1595 
1596     /**
1597      * Sets inertiaScroll enabled
1598      * @param {boolean} enabled
1599      */
1600     setInertiaScrollEnabled: function (enabled) {
1601         this.inertiaScrollEnabled = enabled;
1602     },
1603 
1604     /**
1605      * Returns whether inertiaScroll is enabled
1606      * @returns {boolean}
1607      */
1608     isInertiaScrollEnabled: function () {
1609         return this.inertiaScrollEnabled;
1610     },
1611 
1612     /**
1613      * Gets inner container of ScrollView. Inner container is the container of ScrollView's children.
1614      * @returns {ccui.Layout}
1615      */
1616     getInnerContainer: function () {
1617         return this._innerContainer;
1618     },
1619 
1620     /**
1621      * Sets LayoutType of ccui.ScrollView.
1622      * @param {ccui.Layout.ABSOLUTE|ccui.Layout.LINEAR_VERTICAL|ccui.Layout.LINEAR_HORIZONTAL|ccui.Layout.RELATIVE} type
1623      */
1624     setLayoutType: function (type) {
1625         this._innerContainer.setLayoutType(type);
1626     },
1627 
1628     /**
1629      * Returns the layout type of ccui.ScrollView.
1630      * @returns {ccui.Layout.ABSOLUTE|ccui.Layout.LINEAR_VERTICAL|ccui.Layout.LINEAR_HORIZONTAL|ccui.Layout.RELATIVE}
1631      */
1632     getLayoutType: function () {
1633         return this._innerContainer.getLayoutType();
1634     },
1635 
1636     _doLayout: function () {
1637         if (!this._doLayoutDirty)
1638             return;
1639         this._doLayoutDirty = false;
1640     },
1641 
1642     /**
1643      * Returns the "class name" of ccui.ScrollView.
1644      * @returns {string}
1645      */
1646     getDescription: function () {
1647         return "ScrollView";
1648     },
1649 
1650     _createCloneInstance: function(){
1651         return ccui.ScrollView.create();
1652     },
1653 
1654     _copyClonedWidgetChildren: function (model) {
1655         ccui.Layout.prototype._copyClonedWidgetChildren.call(this, model);
1656     },
1657 
1658     _copySpecialProperties: function (scrollView) {
1659         if(scrollView instanceof ccui.ScrollView) {
1660             ccui.Layout.prototype._copySpecialProperties.call(this, scrollView);
1661             this.setInnerContainerSize(scrollView.getInnerContainerSize());
1662             this.setDirection(scrollView.direction);
1663             this.setBounceEnabled(scrollView.bounceEnabled);
1664             this.setInertiaScrollEnabled(scrollView.inertiaScrollEnabled);
1665             this._scrollViewEventListener = scrollView._scrollViewEventListener;
1666             this._scrollViewEventSelector = scrollView._scrollViewEventSelector;
1667         }
1668     },
1669 
1670     /**
1671      * Returns a node by tag
1672      * @param {Number} tag
1673      * @returns {cc.Node}
1674      * @deprecated  since v3.0, please use getChildByTag instead.
1675      */
1676     getNodeByTag: function (tag) {
1677         return this._innerContainer.getNodeByTag(tag);
1678     },
1679 
1680     /**
1681      * Returns all nodes of inner container
1682      * @returns {Array}
1683      * @deprecated since v3.0, please use getChildren instead.
1684      */
1685     getNodes: function () {
1686         return this._innerContainer.getNodes();
1687     },
1688 
1689     /**
1690      * Removes a node from ccui.ScrollView.
1691      * @param {cc.Node} node
1692      * @deprecated since v3.0, please use removeChild instead.
1693      */
1694     removeNode: function (node) {
1695         this._innerContainer.removeNode(node);
1696     },
1697 
1698     /**
1699      * Removes a node by tag
1700      * @param {Number} tag
1701      * @deprecated since v3.0, please use removeChildByTag instead.
1702      */
1703     removeNodeByTag: function (tag) {
1704         this._innerContainer.removeNodeByTag(tag);
1705     },
1706 
1707     /**
1708      * Remove all node from ccui.ScrollView.
1709      * @deprecated since v3.0, please use removeAllChildren instead.
1710      */
1711     removeAllNodes: function () {
1712         this._innerContainer.removeAllNodes();
1713     },
1714 
1715     /**
1716      * Add node for scrollView
1717      * @param {cc.Node} node
1718      * @param {Number} zOrder
1719      * @param {Number} tag
1720      * @deprecated since v3.0, please use addChild instead.
1721      */
1722     addNode: function (node, zOrder, tag) {
1723         this._innerContainer.addNode(node, zOrder, tag);
1724     }
1725 });
1726 
1727 var _p = ccui.ScrollView.prototype;
1728 
1729 // Extended properties
1730 /** @expose */
1731 _p.innerWidth;
1732 cc.defineGetterSetter(_p, "innerWidth", _p._getInnerWidth, _p._setInnerWidth);
1733 /** @expose */
1734 _p.innerHeight;
1735 cc.defineGetterSetter(_p, "innerHeight", _p._getInnerHeight, _p._setInnerHeight);
1736 
1737 _p = null;
1738 
1739 /**
1740  * allocates and initializes a UIScrollView.
1741  * @deprecated since v3.0, please use new ccui.ScrollView() instead.
1742  * @return {ccui.ScrollView}
1743  * @example
1744  * // example
1745  * var uiScrollView = ccui.ScrollView.create();
1746  */
1747 ccui.ScrollView.create = function () {
1748     return new ccui.ScrollView();
1749 };
1750 
1751 // Constants
1752 //ScrollView direction
1753 /**
1754  * The none flag of ccui.ScrollView's direction.
1755  * @constant
1756  * @type {number}
1757  */
1758 ccui.ScrollView.DIR_NONE = 0;
1759 /**
1760  * The vertical flag of ccui.ScrollView's direction.
1761  * @constant
1762  * @type {number}
1763  */
1764 ccui.ScrollView.DIR_VERTICAL = 1;
1765 /**
1766  * The horizontal flag of ccui.ScrollView's direction.
1767  * @constant
1768  * @type {number}
1769  */
1770 ccui.ScrollView.DIR_HORIZONTAL = 2;
1771 /**
1772  * The both flag of ccui.ScrollView's direction.
1773  * @constant
1774  * @type {number}
1775  */
1776 ccui.ScrollView.DIR_BOTH = 3;
1777 
1778 //ScrollView event
1779 /**
1780  * The flag scroll to top of ccui.ScrollView's event.
1781  * @constant
1782  * @type {number}
1783  */
1784 ccui.ScrollView.EVENT_SCROLL_TO_TOP = 0;
1785 /**
1786  * The flag scroll to bottom of ccui.ScrollView's event.
1787  * @constant
1788  * @type {number}
1789  */
1790 ccui.ScrollView.EVENT_SCROLL_TO_BOTTOM = 1;
1791 /**
1792  * The flag scroll to left of ccui.ScrollView's event.
1793  * @constant
1794  * @type {number}
1795  */
1796 ccui.ScrollView.EVENT_SCROLL_TO_LEFT = 2;
1797 /**
1798  * The flag scroll to right of ccui.ScrollView's event.
1799  * @constant
1800  * @type {number}
1801  */
1802 ccui.ScrollView.EVENT_SCROLL_TO_RIGHT = 3;
1803 /**
1804  * The scrolling flag of ccui.ScrollView's event.
1805  * @constant
1806  * @type {number}
1807  */
1808 ccui.ScrollView.EVENT_SCROLLING = 4;
1809 /**
1810  * The flag bounce top of ccui.ScrollView's event.
1811  * @constant
1812  * @type {number}
1813  */
1814 ccui.ScrollView.EVENT_BOUNCE_TOP = 5;
1815 /**
1816  * The flag bounce bottom of ccui.ScrollView's event.
1817  * @constant
1818  * @type {number}
1819  */
1820 ccui.ScrollView.EVENT_BOUNCE_BOTTOM = 6;
1821 /**
1822  * The flag bounce left of ccui.ScrollView's event.
1823  * @constant
1824  * @type {number}
1825  */
1826 ccui.ScrollView.EVENT_BOUNCE_LEFT = 7;
1827 /**
1828  * The flag bounce right of ccui.ScrollView's event.
1829  * @constant
1830  * @type {number}
1831  */
1832 ccui.ScrollView.EVENT_BOUNCE_RIGHT = 8;
1833 
1834 /**
1835  * The auto scroll max speed of ccui.ScrollView.
1836  * @constant
1837  * @type {number}
1838  */
1839 ccui.ScrollView.AUTO_SCROLL_MAX_SPEED = 1000;
1840 
1841 /**
1842  * @ignore
1843  */
1844 ccui.ScrollView.SCROLLDIR_UP = cc.p(0, 1);
1845 ccui.ScrollView.SCROLLDIR_DOWN = cc.p(0, -1);
1846 ccui.ScrollView.SCROLLDIR_LEFT = cc.p(-1, 0);
1847 ccui.ScrollView.SCROLLDIR_RIGHT = cc.p(1, 0);