1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3 
  4  http://www.cocos2d-x.org
  5 
  6  Permission is hereby granted, free of charge, to any person obtaining a copy
  7  of this software and associated documentation files (the "Software"), to deal
  8  in the Software without restriction, including without limitation the rights
  9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10  copies of the Software, and to permit persons to whom the Software is
 11  furnished to do so, subject to the following conditions:
 12 
 13  The above copyright notice and this permission notice shall be included in
 14  all copies or substantial portions of the Software.
 15 
 16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22  THE SOFTWARE.
 23  ****************************************************************************/
 24 /**
 25  * ScrollView direction
 26  * @type {Object}
 27  */
 28 ccs.ScrollViewDir = {
 29     none: 0,
 30     vertical: 1,
 31     horizontal: 2,
 32     both: 3
 33 };
 34 
 35 /**
 36  * Scrollview event type
 37  * @type {Object}
 38  */
 39 ccs.ScrollViewEventType = {
 40     scrollToTop: 0,
 41     scrollToBottom: 1,
 42     scrollToLeft: 2,
 43     scrollToRight: 3,
 44     scrolling: 4,
 45     bounceTop: 5,
 46     bounceBottom: 6,
 47     bounceLeft: 7,
 48     bounceRight: 8
 49 };
 50 ccs.AUTOSCROLLMAXSPEED = 1000;
 51 ccs.SCROLLDIR_UP = cc.p(0, 1);
 52 ccs.SCROLLDIR_DOWN = cc.p(0, -1);
 53 ccs.SCROLLDIR_LEFT = cc.p(-1, 0);
 54 ccs.SCROLLDIR_RIGHT = cc.p(1, 0);
 55 /**
 56  * Base class for ccs.UIScrollView
 57  * @class
 58  * @extends ccs.UILayout
 59  */
 60 ccs.UIScrollView = ccs.UILayout.extend(/** @lends ccs.UIScrollView# */{
 61     _innerContainer: null,
 62     _direction: null,
 63     _touchBeganPoint: null,
 64     _touchMovedPoint: null,
 65     _touchEndedPoint: null,
 66     _touchMovingPoint: null,
 67     _autoScrollDir: null,
 68     _topBoundary: 0,//test
 69     _bottomBoundary: 0,//test
 70     _leftBoundary: 0,
 71     _rightBoundary: 0,
 72     _bounceTopBoundary: 0,
 73     _bounceBottomBoundary: 0,
 74     _bounceLeftBoundary: 0,
 75     _bounceRightBoundary: 0,
 76     _autoScroll: false,
 77     _autoScrollAddUpTime: 0,
 78     _autoScrollOriginalSpeed: 0,
 79     _autoScrollAcceleration: 0,
 80     _isAutoScrollSpeedAttenuated: false,
 81     _needCheckAutoScrollDestination: false,
 82     _autoScrollDestination: null,
 83     _bePressed: false,
 84     _slidTime: 0,
 85     _moveChildPoint: null,
 86     _childFocusCancelOffset: 0,
 87     _leftBounceNeeded: false,
 88     _topBounceNeeded: false,
 89     _rightBounceNeeded: false,
 90     _bottomBounceNeeded: false,
 91     _bounceEnabled: false,
 92     _bouncing: false,
 93     _bounceDir: null,
 94     _bounceOriginalSpeed: 0,
 95     _inertiaScrollEnabled: false,
 96     _scrollViewEventListener: null,
 97     _scrollViewEventSelector: null,
 98     ctor: function () {
 99         ccs.UILayout.prototype.ctor.call(this);
100         this._innerContainer = null;
101         this._direction = ccs.ScrollViewDir.none;
102         this._touchBeganPoint = cc.p(0, 0);
103         this._touchMovedPoint = cc.p(0, 0);
104         this._touchEndedPoint = cc.p(0, 0);
105         this._touchMovingPoint = cc.p(0, 0);
106         this._autoScrollDir = cc.p(0, 0);
107         this._topBoundary = 0;//test
108         this._bottomBoundary = 0;//test
109         this._leftBoundary = 0;
110         this._rightBoundary = 0;
111         this._bounceTopBoundary = 0;
112         this._bounceBottomBoundary = 0;
113         this._bounceLeftBoundary = 0;
114         this._bounceRightBoundary = 0;
115         this._autoScroll = false;
116         this._autoScrollAddUpTime = 0;
117         this._autoScrollOriginalSpeed = 0;
118         this._autoScrollAcceleration = -1000;
119         this._isAutoScrollSpeedAttenuated = false;
120         this._needCheckAutoScrollDestination = false;
121         this._autoScrollDestination = cc.p(0, 0);
122         this._bePressed = false;
123         this._slidTime = 0;
124         this._moveChildPoint = cc.p(0, 0);
125         this._childFocusCancelOffset = 5;
126         this._leftBounceNeeded = false;
127         this._topBounceNeeded = false;
128         this._rightBounceNeeded = false;
129         this._bottomBounceNeeded = false;
130         this._bounceEnabled = false;
131         this._bouncing = false;
132         this._bounceDir = cc.p(0, 0);
133         this._bounceOriginalSpeed = 0;
134         this._inertiaScrollEnabled = true;
135         this._scrollViewEventListener = null;
136         this._scrollViewEventSelector = null;
137     },
138     releaseResoures: function () {
139         this.setUpdateEnabled(false);
140         this.removeAllChildren();
141         this._renderer.removeAllChildren(true);
142         this._renderer.removeFromParent(true);
143 
144         ccs.UILayout.prototype.removeChild.call(this, this._innerContainer);
145 
146         this._children = [];
147     },
148 
149     init: function () {
150         if (ccs.UILayout.prototype.init.call(this)) {
151             this.setUpdateEnabled(true);
152             this.setTouchEnabled(true);
153             this.setClippingEnabled(true);
154             this._innerContainer.setTouchEnabled(false);
155             return true;
156         }
157         return false;
158     },
159 
160     initRenderer: function () {
161         ccs.UILayout.prototype.initRenderer.call(this);
162         this._innerContainer = ccs.UILayout.create();
163         ccs.UILayout.prototype.addChild.call(this, this._innerContainer);
164     },
165 
166     onSizeChanged: function () {
167         ccs.UILayout.prototype.onSizeChanged.call(this);
168         var locSize = this._size;
169         this._topBoundary = locSize.height;
170         this._rightBoundary = locSize.width;
171         var bounceBoundaryParameterX = locSize.width / 3;
172         var bounceBoundaryParameterY = locSize.height / 3;
173         this._bounceTopBoundary = locSize.height - bounceBoundaryParameterY;
174         this._bounceBottomBoundary = bounceBoundaryParameterY;
175         this._bounceLeftBoundary = bounceBoundaryParameterX;
176         this._bounceRightBoundary = this._size.width - bounceBoundaryParameterX;
177         var innerSize = this._innerContainer.getSize();
178         var orginInnerSizeWidth = innerSize.width;
179         var orginInnerSizeHeight = innerSize.height;
180         var innerSizeWidth = Math.max(orginInnerSizeWidth, locSize.width);
181         var innerSizeHeight = Math.max(orginInnerSizeHeight, locSize.height);
182         this._innerContainer.setSize(cc.size(innerSizeWidth, innerSizeHeight));
183         this._innerContainer.setPosition(cc.p(0, locSize.height - this._innerContainer.getSize().height));
184     },
185 
186     setInnerContainerSize: function (size) {
187         var locSize = this._size;
188         var innerSizeWidth = locSize.width;
189         var innerSizeHeight = locSize.height;
190         var originalInnerSize = this._innerContainer.getSize();
191         if (size.width < locSize.width) {
192             cc.log("Inner width <= scrollview width, it will be force sized!");
193         }
194         else {
195             innerSizeWidth = size.width;
196         }
197         if (size.height < locSize.height) {
198             cc.log("Inner height <= scrollview height, it will be force sized!");
199         }
200         else {
201             innerSizeHeight = size.height;
202         }
203         this._innerContainer.setSize(cc.size(innerSizeWidth, innerSizeHeight));
204         switch (this._direction) {
205             case ccs.ScrollViewDir.vertical:
206                 var newInnerSize = this._innerContainer.getSize();
207                 var offset = originalInnerSize.height - newInnerSize.height;
208                 this.scrollChildren(0, offset);
209                 break;
210             case ccs.ScrollViewDir.horizontal:
211                 if (this._innerContainer.getRightInParent() <= locSize.width) {
212                     var newInnerSize = this._innerContainer.getSize();
213                     var offset = originalInnerSize.width - newInnerSize.width;
214                     this.scrollChildren(offset, 0);
215                 }
216                 break;
217             case ccs.ScrollViewDir.both:
218                 var newInnerSize = this._innerContainer.getSize();
219                 var offsetY = originalInnerSize.height - newInnerSize.height;
220                 var offsetX = 0;
221                 if (this._innerContainer.getRightInParent() <= locSize.width) {
222                     offsetX = originalInnerSize.width - newInnerSize.width;
223                 }
224                 this.scrollChildren(offsetX, offsetY);
225                 break;
226             default:
227                 break;
228         }
229     },
230 
231     getInnerContainerSize: function () {
232         return this._innerContainer.getSize();
233     },
234 
235     /**
236      * Add widget
237      * @param {ccs.UIWidget} widget
238      * @returns {boolean}
239      */
240     addChild: function (widget) {
241         return this._innerContainer.addChild(widget);
242     },
243 
244     removeAllChildren: function () {
245         this._innerContainer.removeAllChildren();
246     },
247 
248     /**
249      *  remove widget child override
250      * @param {ccs.UIWidget} child
251      * @returns {boolean}
252      */
253     removeChild: function (child) {
254         return this._innerContainer.removeChild(child);
255     },
256 
257     getChildren: function () {
258         return this._innerContainer.getChildren();
259     },
260 
261     moveChildren: function (offsetX, offsetY) {
262         var pos = this._innerContainer.getPosition();
263         this._moveChildPoint.x = pos.x + offsetX;
264         this._moveChildPoint.y = pos.y + offsetY;
265         this._innerContainer.setPosition(this._moveChildPoint);
266     },
267 
268     autoScrollChildren: function (dt) {
269         var lastTime = this._autoScrollAddUpTime;
270         this._autoScrollAddUpTime += dt;
271         if (this._isAutoScrollSpeedAttenuated) {
272             var nowSpeed = this._autoScrollOriginalSpeed + this._autoScrollAcceleration * this._autoScrollAddUpTime;
273             if (nowSpeed <= 0) {
274                 this.stopAutoScrollChildren();
275                 this.checkNeedBounce();
276             } else {
277                 var timeParam = lastTime * 2 + dt;
278                 var offset = (this._autoScrollOriginalSpeed + this._autoScrollAcceleration * timeParam * 0.5) * dt;
279                 var offsetX = offset * this._autoScrollDir.x;
280                 var offsetY = offset * this._autoScrollDir.y;
281                 if (!this.scrollChildren(offsetX, offsetY)) {
282                     this.stopAutoScrollChildren();
283                     this.checkNeedBounce();
284                 }
285             }
286         }
287         else {
288             if (this._needCheckAutoScrollDestination) {
289                 var xOffset = this._autoScrollDir.x * dt * this._autoScrollOriginalSpeed;
290                 var yOffset = this._autoScrollDir.y * dt * this._autoScrollOriginalSpeed;
291                 var notDone = this.checkCustomScrollDestination(xOffset, yOffset);
292                 var scrollCheck = this.scrollChildren(xOffset, yOffset);
293                 if (!notDone || !scrollCheck) {
294                     this.stopAutoScrollChildren();
295                     this.checkNeedBounce();
296                 }
297             }
298             else {
299                 if (!this.scrollChildren(this._autoScrollDir.x * dt * this._autoScrollOriginalSpeed, this._autoScrollDir.y * dt * this._autoScrollOriginalSpeed)) {
300                     this.stopAutoScrollChildren();
301                     this.checkNeedBounce();
302                 }
303             }
304         }
305     },
306 
307     bounceChildren: function (dt) {
308         var locSpeed = this._bounceOriginalSpeed;
309         var locBounceDir = this._bounceDir;
310         if (locSpeed <= 0.0) {
311             this.stopBounceChildren();
312         }
313         if (!this.bounceScrollChildren(locBounceDir.x * dt * locSpeed, locBounceDir.y * dt * locSpeed)) {
314             this.stopBounceChildren();
315         }
316     },
317 
318     checkNeedBounce: function () {
319         if (!this._bounceEnabled) {
320             return false;
321         }
322         this.checkBounceBoundary();
323         if (this._topBounceNeeded || this._bottomBounceNeeded || this._leftBounceNeeded || this._rightBounceNeeded) {
324             if (this._topBounceNeeded && this._leftBounceNeeded) {
325                 var scrollVector = cc.pSub(cc.p(0.0, this._size.height), cc.p(this._innerContainer.getLeftInParent(), this._innerContainer.getTopInParent()));
326                 var orSpeed = cc.pLength(scrollVector) / 0.2;
327                 this._bounceDir = cc.pNormalize(scrollVector);
328                 this.startBounceChildren(orSpeed);
329             }
330             else if (this._topBounceNeeded && this._rightBounceNeeded) {
331                 var scrollVector = cc.pSub(cc.p(this._size.width, this._size.height), cc.p(this._innerContainer.getRightInParent(), this._innerContainer.getTopInParent()));
332                 var orSpeed = cc.pLength(scrollVector) / 0.2;
333                 this._bounceDir = cc.pNormalize(scrollVector);
334                 this.startBounceChildren(orSpeed);
335             }
336             else if (this._bottomBounceNeeded && this._leftBounceNeeded) {
337                 var scrollVector = cc.pSub(cc.p(0, 0), cc.p(this._innerContainer.getLeftInParent(), this._innerContainer.getBottomInParent()));
338                 var orSpeed = cc.pLength(scrollVector) / 0.2;
339                 this._bounceDir = cc.pNormalize(scrollVector);
340                 this.startBounceChildren(orSpeed);
341             }
342             else if (this._bottomBounceNeeded && this._rightBounceNeeded) {
343                 var scrollVector = cc.pSub(cc.p(this._size.width, 0.0), cc.p(this._innerContainer.getRightInParent(), this._innerContainer.getBottomInParent()));
344                 var orSpeed = cc.pLength(scrollVector) / 0.2;
345                 this._bounceDir = cc.pNormalize(scrollVector);
346                 this.startBounceChildren(orSpeed);
347             }
348             else if (this._topBounceNeeded) {
349                 var scrollVector = cc.pSub(cc.p(0, this._size.height), cc.p(0.0, this._innerContainer.getTopInParent()));
350                 var orSpeed = cc.pLength(scrollVector) / 0.2;
351                 this._bounceDir = cc.pNormalize(scrollVector);
352                 this.startBounceChildren(orSpeed);
353             }
354             else if (this._bottomBounceNeeded) {
355                 var scrollVector = cc.pSub(cc.p(0, 0), cc.p(0.0, this._innerContainer.getBottomInParent()));
356                 var orSpeed = cc.pLength(scrollVector) / 0.2;
357                 this._bounceDir = cc.pNormalize(scrollVector);
358                 this.startBounceChildren(orSpeed);
359             }
360             else if (this._leftBounceNeeded) {
361                 var scrollVector = cc.pSub(cc.p(0, 0), cc.p(this._innerContainer.getLeftInParent(), 0.0));
362                 var orSpeed = cc.pLength(scrollVector) / 0.2;
363                 this._bounceDir = cc.pNormalize(scrollVector);
364                 this.startBounceChildren(orSpeed);
365             }
366             else if (this._rightBounceNeeded) {
367                 var scrollVector = cc.pSub(cc.p(this._size.width, 0), cc.p(this._innerContainer.getRightInParent(), 0.0));
368                 var orSpeed = cc.pLength(scrollVector) / 0.2;
369                 this._bounceDir = cc.pNormalize(scrollVector);
370                 this.startBounceChildren(orSpeed);
371             }
372             return true;
373         }
374         return false;
375     },
376 
377     checkBounceBoundary: function () {
378         var icBottomPos = this._innerContainer.getBottomInParent();
379         if (icBottomPos > this._bottomBoundary) {
380             this.scrollToBottomEvent();
381             this._bottomBounceNeeded = true;
382         }
383         else {
384             this._bottomBounceNeeded = false;
385         }
386         var icTopPos = this._innerContainer.getTopInParent();
387         if (icTopPos < this._topBoundary) {
388             this.scrollToTopEvent();
389             this._topBounceNeeded = true;
390         }
391         else {
392             this._topBounceNeeded = false;
393         }
394         var icRightPos = this._innerContainer.getRightInParent();
395         if (icRightPos < this._rightBoundary) {
396             this.scrollToRightEvent();
397             this._rightBounceNeeded = true;
398         }
399         else {
400             this._rightBounceNeeded = false;
401         }
402         var icLeftPos = this._innerContainer.getLeftInParent();
403         if (icLeftPos > this._leftBoundary) {
404             this.scrollToLeftEvent();
405             this._leftBounceNeeded = true;
406         }
407         else {
408             this._leftBounceNeeded = false;
409         }
410     },
411 
412     startBounceChildren: function (v) {
413         this._bounceOriginalSpeed = v;
414         this._bouncing = true;
415     },
416 
417     stopBounceChildren: function () {
418         this._bouncing = false;
419         this._bounceOriginalSpeed = 0.0;
420         this._leftBounceNeeded = false;
421         this._rightBounceNeeded = false;
422         this._topBounceNeeded = false;
423         this._bottomBounceNeeded = false;
424     },
425 
426     startAutoScrollChildrenWithOriginalSpeed: function (dir, v, attenuated, acceleration) {
427         this.stopAutoScrollChildren();
428         this._autoScrollDir = dir;
429         this._isAutoScrollSpeedAttenuated = attenuated;
430         this._autoScrollOriginalSpeed = v;
431         this._autoScroll = true;
432         this._autoScrollAcceleration = acceleration;
433     },
434 
435     startAutoScrollChildrenWithDestination: function (des, time, attenuated) {
436         this._needCheckAutoScrollDestination = false;
437         this._autoScrollDestination = des;
438         var dis = cc.pSub(des, this._innerContainer.getPosition());
439         var dir = cc.pNormalize(dis);
440         var orSpeed = 0.0;
441         var acceleration = -1000.0;
442         var disLength = cc.pLength(dis);
443         if (attenuated) {
444             acceleration = -(2 * disLength) / (time * time);
445             orSpeed = 2 * disLength / time;
446         }
447         else {
448             this._needCheckAutoScrollDestination = true;
449             orSpeed = disLength / time;
450         }
451         this.startAutoScrollChildrenWithOriginalSpeed(dir, orSpeed, attenuated, acceleration);
452     },
453 
454     jumpToDestination: function (des) {
455         var finalOffsetX = des.x;
456         var finalOffsetY = des.y;
457         switch (this._direction) {
458             case cc.ScrollViewDir.vertical:
459                 if (des.y <= 0) {
460                     finalOffsetY = Math.max(des.y, this._size.height - this._innerContainer.getSize().height);
461                 }
462                 break;
463             case cc.ScrollViewDir.horizontal:
464                 if (des.x <= 0) {
465                     finalOffsetX = Math.max(des.x, this._size.width - this._innerContainer.getSize().width);
466                 }
467                 break;
468             case cc.ScrollViewDir.both:
469                 if (des.y <= 0) {
470                     finalOffsetY = Math.max(des.y, this._size.height - this._innerContainer.getSize().height);
471                 }
472                 if (des.x <= 0) {
473                     finalOffsetX = Math.max(des.x, this._size.width - this._innerContainer.getSize().width);
474                 }
475                 break;
476             default:
477                 break;
478         }
479         this._innerContainer.setPosition(cc.p(finalOffsetX, finalOffsetY));
480     },
481 
482 
483     stopAutoScrollChildren: function () {
484         this._autoScroll = false;
485         this._autoScrollOriginalSpeed = 0;
486         this._autoScrollAddUpTime = 0;
487     },
488 
489     bounceScrollChildren: function (touchOffsetX, touchOffsetY) {
490         var scrollEnabled = true;
491         if (touchOffsetX > 0.0 && touchOffsetY > 0.0) //first quadrant //bounce to top-right
492         {
493             var realOffsetX = touchOffsetX;
494             var realOffsetY = touchOffsetY;
495             var icRightPos = this._innerContainer.getRightInParent();
496             if (icRightPos + realOffsetX >= this._rightBoundary) {
497                 realOffsetX = this._rightBoundary - icRightPos;
498                 this.bounceRightEvent();
499                 scrollEnabled = false;
500             }
501             var icTopPos = this._innerContainer.getTopInParent();
502             if (icTopPos + touchOffsetY >= this._topBoundary) {
503                 realOffsetY = this._topBoundary - icTopPos;
504                 this.bounceTopEvent();
505                 scrollEnabled = false;
506             }
507             this.moveChildren(realOffsetX, realOffsetY);
508         }
509         else if (touchOffsetX < 0.0 && touchOffsetY > 0.0) //second quadrant //bounce to top-left
510         {
511             var realOffsetX = touchOffsetX;
512             var realOffsetY = touchOffsetY;
513             var icLefrPos = this._innerContainer.getLeftInParent();
514             if (icLefrPos + realOffsetX <= this._leftBoundary) {
515                 realOffsetX = this._leftBoundary - icLefrPos;
516                 this.bounceLeftEvent();
517                 scrollEnabled = false;
518             }
519             var icTopPos = this._innerContainer.getTopInParent();
520             if (icTopPos + touchOffsetY >= this._topBoundary) {
521                 realOffsetY = this._topBoundary - icTopPos;
522                 this.bounceTopEvent();
523                 scrollEnabled = false;
524             }
525             this.moveChildren(realOffsetX, realOffsetY);
526         }
527         else if (touchOffsetX < 0.0 && touchOffsetY < 0.0) //third quadrant //bounce to bottom-left
528         {
529             var realOffsetX = touchOffsetX;
530             var realOffsetY = touchOffsetY;
531             var icLefrPos = this._innerContainer.getLeftInParent();
532             if (icLefrPos + realOffsetX <= this._leftBoundary) {
533                 realOffsetX = this._leftBoundary - icLefrPos;
534                 this.bounceLeftEvent();
535                 scrollEnabled = false;
536             }
537             var icBottomPos = this._innerContainer.getBottomInParent();
538             if (icBottomPos + touchOffsetY <= this._bottomBoundary) {
539                 realOffsetY = this._bottomBoundary - icBottomPos;
540                 this.bounceBottomEvent();
541                 scrollEnabled = false;
542             }
543             this.moveChildren(realOffsetX, realOffsetY);
544         }
545         else if (touchOffsetX > 0.0 && touchOffsetY < 0.0) //forth quadrant //bounce to bottom-right
546         {
547             var realOffsetX = touchOffsetX;
548             var realOffsetY = touchOffsetY;
549             var icRightPos = this._innerContainer.getRightInParent();
550             if (icRightPos + realOffsetX >= this._rightBoundary) {
551                 realOffsetX = this._rightBoundary - icRightPos;
552                 this.bounceRightEvent();
553                 scrollEnabled = false;
554             }
555             var icBottomPos = this._innerContainer.getBottomInParent();
556             if (icBottomPos + touchOffsetY <= this._bottomBoundary) {
557                 realOffsetY = this._bottomBoundary - icBottomPos;
558                 this.bounceBottomEvent();
559                 scrollEnabled = false;
560             }
561             this.moveChildren(realOffsetX, realOffsetY);
562         }
563         else if (touchOffsetX == 0.0 && touchOffsetY > 0.0) // bounce to top
564         {
565             var realOffsetY = touchOffsetY;
566             var icTopPos = this._innerContainer.getTopInParent();
567             if (icTopPos + touchOffsetY >= this._topBoundary) {
568                 realOffsetY = this._topBoundary - icTopPos;
569                 this.bounceTopEvent();
570                 scrollEnabled = false;
571             }
572             this.moveChildren(0.0, realOffsetY);
573         }
574         else if (touchOffsetX == 0.0 && touchOffsetY < 0.0) //bounce to bottom
575         {
576             var realOffsetY = touchOffsetY;
577             var icBottomPos = this._innerContainer.getBottomInParent();
578             if (icBottomPos + touchOffsetY <= this._bottomBoundary) {
579                 realOffsetY = this._bottomBoundary - icBottomPos;
580                 this.bounceBottomEvent();
581                 scrollEnabled = false;
582             }
583             this.moveChildren(0.0, realOffsetY);
584         }
585         else if (touchOffsetX > 0.0 && touchOffsetY == 0.0) //bounce to right
586         {
587             var realOffsetX = touchOffsetX;
588             var icRightPos = this._innerContainer.getRightInParent();
589             if (icRightPos + realOffsetX >= this._rightBoundary) {
590                 realOffsetX = this._rightBoundary - icRightPos;
591                 this.bounceRightEvent();
592                 scrollEnabled = false;
593             }
594             this.moveChildren(realOffsetX, 0.0);
595         }
596         else if (touchOffsetX < 0.0 && touchOffsetY == 0.0) //bounce to left
597         {
598             var realOffsetX = touchOffsetX;
599             var icLeftPos = this._innerContainer.getLeftInParent();
600             if (icLeftPos + realOffsetX <= this._leftBoundary) {
601                 realOffsetX = this._leftBoundary - icLeftPos;
602                 this.bounceLeftEvent();
603                 scrollEnabled = false;
604             }
605             this.moveChildren(realOffsetX, 0.0);
606         }
607         return scrollEnabled;
608     },
609 
610     checkCustomScrollDestination: function (touchOffsetX, touchOffsetY) {
611         var scrollEnabled = true;
612         switch (this._direction) {
613             case ccs.ScrollViewDir.vertical: // vertical
614                 if (this._autoScrollDir.y > 0) {
615                     var icBottomPos = this._innerContainer.getBottomInParent();
616                     if (icBottomPos + touchOffsetY >= this._autoScrollDestination.y) {
617                         touchOffsetY = this._autoScrollDestination.y - icBottomPos;
618                         scrollEnabled = false;
619                     }
620                 }
621                 else {
622                     var icBottomPos = this._innerContainer.getBottomInParent();
623                     if (icBottomPos + touchOffsetY <= this._autoScrollDestination.y) {
624                         touchOffsetY = this._autoScrollDestination.y - icBottomPos;
625                         scrollEnabled = false;
626                     }
627                 }
628                 break;
629             case ccs.ScrollViewDir.horizontal: // horizontal
630                 if (this._autoScrollDir.x > 0) {
631                     var icLeftPos = this._innerContainer.getLeftInParent();
632                     if (icLeftPos + touchOffsetX >= this._autoScrollDestination.x) {
633                         touchOffsetX = this._autoScrollDestination.x - icLeftPos;
634                         scrollEnabled = false;
635                     }
636                 }
637                 else {
638                     var icLeftPos = this._innerContainer.getLeftInParent();
639                     if (icLeftPos + touchOffsetX <= this._autoScrollDestination.x) {
640                         touchOffsetX = this._autoScrollDestination.x - icLeftPos;
641                         scrollEnabled = false;
642                     }
643                 }
644                 break;
645             case ccs.ScrollViewDir.both:
646                 if (touchOffsetX > 0.0 && touchOffsetY > 0.0) // up right
647                 {
648                     var icLeftPos = this._innerContainer.getLeftInParent();
649                     if (icLeftPos + touchOffsetX >= this._autoScrollDestination.x) {
650                         touchOffsetX = this._autoScrollDestination.x - icLeftPos;
651                         scrollEnabled = false;
652                     }
653                     var icBottomPos = this._innerContainer.getBottomInParent();
654                     if (icBottomPos + touchOffsetY >= this._autoScrollDestination.y) {
655                         touchOffsetY = this._autoScrollDestination.y - icBottomPos;
656                         scrollEnabled = false;
657                     }
658                 }
659                 else if (touchOffsetX < 0.0 && touchOffsetY > 0.0) // up left
660                 {
661                     var icRightPos = this._innerContainer.getRightInParent();
662                     if (icRightPos + touchOffsetX <= this._autoScrollDestination.x) {
663                         touchOffsetX = this._autoScrollDestination.x - icRightPos;
664                         scrollEnabled = false;
665                     }
666                     var icBottomPos = this._innerContainer.getBottomInParent();
667                     if (icBottomPos + touchOffsetY >= this._autoScrollDestination.y) {
668                         touchOffsetY = this._autoScrollDestination.y - icBottomPos;
669                         scrollEnabled = false;
670                     }
671                 }
672                 else if (touchOffsetX < 0.0 && touchOffsetY < 0.0) // down left
673                 {
674                     var icRightPos = this._innerContainer.getRightInParent();
675                     if (icRightPos + touchOffsetX <= this._autoScrollDestination.x) {
676                         touchOffsetX = this._autoScrollDestination.x - icRightPos;
677                         scrollEnabled = false;
678                     }
679                     var icTopPos = this._innerContainer.getTopInParent();
680                     if (icTopPos + touchOffsetY <= this._autoScrollDestination.y) {
681                         touchOffsetY = this._autoScrollDestination.y - icTopPos;
682                         scrollEnabled = false;
683                     }
684                 }
685                 else if (touchOffsetX > 0.0 && touchOffsetY < 0.0) // down right
686                 {
687                     var icLeftPos = this._innerContainer.getLeftInParent();
688                     if (icLeftPos + touchOffsetX >= this._autoScrollDestination.x) {
689                         touchOffsetX = this._autoScrollDestination.x - icLeftPos;
690                         scrollEnabled = false;
691                     }
692                     var icTopPos = this._innerContainer.getTopInParent();
693                     if (icTopPos + touchOffsetY <= this._autoScrollDestination.y) {
694                         touchOffsetY = this._autoScrollDestination.y - icTopPos;
695                         scrollEnabled = false;
696                     }
697                 }
698                 else if (touchOffsetX == 0.0 && touchOffsetY > 0.0) // up
699                 {
700                     var icBottomPos = this._innerContainer.getBottomInParent();
701                     if (icBottomPos + touchOffsetY >= this._autoScrollDestination.y) {
702                         touchOffsetY = this._autoScrollDestination.y - icBottomPos;
703                         scrollEnabled = false;
704                     }
705                 }
706                 else if (touchOffsetX < 0.0 && touchOffsetY == 0.0) // left
707                 {
708                     var icRightPos = this._innerContainer.getRightInParent();
709                     if (icRightPos + touchOffsetX <= this._autoScrollDestination.x) {
710                         touchOffsetX = this._autoScrollDestination.x - icRightPos;
711                         scrollEnabled = false;
712                     }
713                 }
714                 else if (touchOffsetX == 0.0 && touchOffsetY < 0.0) // down
715                 {
716                     var icTopPos = this._innerContainer.getTopInParent();
717                     if (icTopPos + touchOffsetY <= this._autoScrollDestination.y) {
718                         touchOffsetY = this._autoScrollDestination.y - icTopPos;
719                         scrollEnabled = false;
720                     }
721                 }
722                 else if (touchOffsetX > 0.0 && touchOffsetY == 0.0) // right
723                 {
724                     var icLeftPos = this._innerContainer.getLeftInParent();
725                     if (icLeftPos + touchOffsetX >= this._autoScrollDestination.x) {
726                         touchOffsetX = this._autoScrollDestination.x - icLeftPos;
727                         scrollEnabled = false;
728                     }
729                 }
730                 break;
731             default:
732                 break;
733         }
734         return scrollEnabled;
735     },
736 
737 
738     getCurAutoScrollDistance: function (dt) {
739         this._autoScrollOriginalSpeed -= this._autoScrollAcceleration * dt;
740         return this._autoScrollOriginalSpeed * dt;
741     },
742 
743     scrollChildren: function (touchOffsetX, touchOffsetY) {
744         var scrollEnabled = true;
745         this.scrollingEvent();
746         switch (this._direction) {
747             case ccs.ScrollViewDir.vertical: // vertical
748                 var realOffset = touchOffsetY;
749                 if (this._bounceEnabled) {
750                     var icBottomPos = this._innerContainer.getBottomInParent();
751                     if (icBottomPos + touchOffsetY >= this._bounceBottomBoundary) {
752                         realOffset = this._bounceBottomBoundary - icBottomPos;
753                         this.scrollToBottomEvent();
754                         scrollEnabled = false;
755                     }
756                     var icTopPos = this._innerContainer.getTopInParent();
757                     if (icTopPos + touchOffsetY <= this._bounceTopBoundary) {
758                         realOffset = this._bounceTopBoundary - icTopPos;
759                         this.scrollToTopEvent();
760                         scrollEnabled = false;
761                     }
762                 }
763                 else {
764                     var icBottomPos = this._innerContainer.getBottomInParent();
765                     if (icBottomPos + touchOffsetY >= this._bottomBoundary) {
766                         realOffset = this._bottomBoundary - icBottomPos;
767                         this.scrollToBottomEvent();
768                         scrollEnabled = false;
769                     }
770                     var icTopPos = this._innerContainer.getTopInParent();
771                     if (icTopPos + touchOffsetY <= this._topBoundary) {
772                         realOffset = this._topBoundary - icTopPos;
773                         this.scrollToTopEvent();
774                         scrollEnabled = false;
775                     }
776                 }
777                 this.moveChildren(0.0, realOffset);
778                 break;
779             case ccs.ScrollViewDir.horizontal: // horizontal
780                 var realOffset = touchOffsetX;
781                 if (this._bounceEnabled) {
782                     var icRightPos = this._innerContainer.getRightInParent();
783                     if (icRightPos + touchOffsetX <= this._bounceRightBoundary) {
784                         realOffset = this._bounceRightBoundary - icRightPos;
785                         this.scrollToRightEvent();
786                         scrollEnabled = false;
787                     }
788                     var icLeftPos = this._innerContainer.getLeftInParent();
789                     if (icLeftPos + touchOffsetX >= this._bounceLeftBoundary) {
790                         realOffset = this._bounceLeftBoundary - icLeftPos;
791                         this.scrollToLeftEvent();
792                         scrollEnabled = false;
793                     }
794                 }
795                 else {
796                     var icRightPos = this._innerContainer.getRightInParent();
797                     if (icRightPos + touchOffsetX <= this._rightBoundary) {
798                         realOffset = this._rightBoundary - icRightPos;
799                         this.scrollToRightEvent();
800                         scrollEnabled = false;
801                     }
802                     var icLeftPos = this._innerContainer.getLeftInParent();
803                     if (icLeftPos + touchOffsetX >= this._leftBoundary) {
804                         realOffset = this._leftBoundary - icLeftPos;
805                         this.scrollToLeftEvent();
806                         scrollEnabled = false;
807                     }
808                 }
809                 this.moveChildren(realOffset, 0.0);
810                 break;
811             case ccs.ScrollViewDir.both:
812                 var realOffsetX = touchOffsetX;
813                 var realOffsetY = touchOffsetY;
814                 if (this._bounceEnabled) {
815                     if (touchOffsetX > 0.0 && touchOffsetY > 0.0) // up right
816                     {
817                         var icLeftPos = this._innerContainer.getLeftInParent();
818                         if (icLeftPos + touchOffsetX >= this._bounceLeftBoundary) {
819                             realOffsetX = this._bounceLeftBoundary - icLeftPos;
820                             this.scrollToLeftEvent();
821                             scrollEnabled = false;
822                         }
823                         var icBottomPos = this._innerContainer.getBottomInParent();
824                         if (icBottomPos + touchOffsetY >= this._bounceBottomBoundary) {
825                             realOffsetY = this._bounceBottomBoundary - icBottomPos;
826                             this.scrollToBottomEvent();
827                             scrollEnabled = false;
828                         }
829                     }
830                     else if (touchOffsetX < 0.0 && touchOffsetY > 0.0) // up left
831                     {
832                         var icRightPos = this._innerContainer.getRightInParent();
833                         if (icRightPos + touchOffsetX <= this._bounceRightBoundary) {
834                             realOffsetX = this._bounceRightBoundary - icRightPos;
835                             this.scrollToRightEvent();
836                             scrollEnabled = false;
837                         }
838                         var icBottomPos = this._innerContainer.getBottomInParent();
839                         if (icBottomPos + touchOffsetY >= this._bounceBottomBoundary) {
840                             realOffsetY = this._bounceBottomBoundary - icBottomPos;
841                             this.scrollToBottomEvent();
842                             scrollEnabled = false;
843                         }
844                     }
845                     else if (touchOffsetX < 0.0 && touchOffsetY < 0.0) // down left
846                     {
847                         var icRightPos = this._innerContainer.getRightInParent();
848                         if (icRightPos + touchOffsetX <= this._bounceRightBoundary) {
849                             realOffsetX = this._bounceRightBoundary - icRightPos;
850                             this.scrollToRightEvent();
851                             scrollEnabled = false;
852                         }
853                         var icTopPos = this._innerContainer.getTopInParent();
854                         if (icTopPos + touchOffsetY <= this._bounceTopBoundary) {
855                             realOffsetY = this._bounceTopBoundary - icTopPos;
856                             this.scrollToTopEvent();
857                             scrollEnabled = false;
858                         }
859                     }
860                     else if (touchOffsetX > 0.0 && touchOffsetY < 0.0) // down right
861                     {
862                         var icLeftPos = this._innerContainer.getLeftInParent();
863                         if (icLeftPos + touchOffsetX >= this._bounceLeftBoundary) {
864                             realOffsetX = this._bounceLeftBoundary - icLeftPos;
865                             this.scrollToLeftEvent();
866                             scrollEnabled = false;
867                         }
868                         var icTopPos = this._innerContainer.getTopInParent();
869                         if (icTopPos + touchOffsetY <= this._bounceTopBoundary) {
870                             realOffsetY = this._bounceTopBoundary - icTopPos;
871                             this.scrollToTopEvent();
872                             scrollEnabled = false;
873                         }
874                     }
875                     else if (touchOffsetX == 0.0 && touchOffsetY > 0.0) // up
876                     {
877                         var icBottomPos = this._innerContainer.getBottomInParent();
878                         if (icBottomPos + touchOffsetY >= this._bounceBottomBoundary) {
879                             realOffsetY = this._bounceBottomBoundary - icBottomPos;
880                             this.scrollToBottomEvent();
881                             scrollEnabled = false;
882                         }
883                     }
884                     else if (touchOffsetX < 0.0 && touchOffsetY == 0.0) // left
885                     {
886                         var icRightPos = this._innerContainer.getRightInParent();
887                         if (icRightPos + touchOffsetX <= this._bounceRightBoundary) {
888                             realOffsetX = this._bounceRightBoundary - icRightPos;
889                             this.scrollToRightEvent();
890                             scrollEnabled = false;
891                         }
892                     }
893                     else if (touchOffsetX == 0.0 && touchOffsetY < 0.0) // down
894                     {
895                         var icTopPos = this._innerContainer.getTopInParent();
896                         if (icTopPos + touchOffsetY <= this._bounceTopBoundary) {
897                             realOffsetY = this._bounceTopBoundary - icTopPos;
898                             this.scrollToTopEvent();
899                             scrollEnabled = false;
900                         }
901                     }
902                     else if (touchOffsetX > 0.0 && touchOffsetY == 0.0) // right
903                     {
904                         var icLeftPos = this._innerContainer.getLeftInParent();
905                         if (icLeftPos + touchOffsetX >= this._bounceLeftBoundary) {
906                             realOffsetX = this._bounceLeftBoundary - icLeftPos;
907                             this.scrollToLeftEvent();
908                             scrollEnabled = false;
909                         }
910                     }
911                 }
912                 else {
913                     if (touchOffsetX > 0.0 && touchOffsetY > 0.0) // up right
914                     {
915                         var icLeftPos = this._innerContainer.getLeftInParent();
916                         if (icLeftPos + touchOffsetX >= this._leftBoundary) {
917                             realOffsetX = this._leftBoundary - icLeftPos;
918                             this.scrollToLeftEvent();
919                             scrollEnabled = false;
920                         }
921                         var icBottomPos = this._innerContainer.getBottomInParent();
922                         if (icBottomPos + touchOffsetY >= this._bottomBoundary) {
923                             realOffsetY = this._bottomBoundary - icBottomPos;
924                             this.scrollToBottomEvent();
925                             scrollEnabled = false;
926                         }
927                     }
928                     else if (touchOffsetX < 0.0 && touchOffsetY > 0.0) // up left
929                     {
930                         var icRightPos = this._innerContainer.getRightInParent();
931                         if (icRightPos + touchOffsetX <= this._rightBoundary) {
932                             realOffsetX = this._rightBoundary - icRightPos;
933                             this.scrollToRightEvent();
934                             scrollEnabled = false;
935                         }
936                         var icBottomPos = this._innerContainer.getBottomInParent();
937                         if (icBottomPos + touchOffsetY >= this._bottomBoundary) {
938                             realOffsetY = this._bottomBoundary - icBottomPos;
939                             this.scrollToBottomEvent();
940                             scrollEnabled = false;
941                         }
942                     }
943                     else if (touchOffsetX < 0 && touchOffsetY < 0) // down left
944                     {
945                         var icRightPos = this._innerContainer.getRightInParent();
946                         if (icRightPos + touchOffsetX <= this._rightBoundary) {
947                             realOffsetX = this._rightBoundary - icRightPos;
948                             this.scrollToRightEvent();
949                             scrollEnabled = false;
950                         }
951                         var icTopPos = this._innerContainer.getTopInParent();
952                         if (icTopPos + touchOffsetY <= this._topBoundary) {
953                             realOffsetY = this._topBoundary - icTopPos;
954                             this.scrollToTopEvent();
955                             scrollEnabled = false;
956                         }
957                     }
958                     else if (touchOffsetX > 0 && touchOffsetY < 0) // down right
959                     {
960                         var icLeftPos = this._innerContainer.getLeftInParent();
961                         if (icLeftPos + touchOffsetX >= this._leftBoundary) {
962                             realOffsetX = this._leftBoundary - icLeftPos;
963                             this.scrollToLeftEvent();
964                             scrollEnabled = false;
965                         }
966                         var icTopPos = this._innerContainer.getTopInParent();
967                         if (icTopPos + touchOffsetY <= this._topBoundary) {
968                             realOffsetY = this._topBoundary - icTopPos;
969                             this.scrollToTopEvent();
970                             scrollEnabled = false;
971                         }
972                     }
973                     else if (touchOffsetX == 0.0 && touchOffsetY > 0.0) // up
974                     {
975                         var icBottomPos = this._innerContainer.getBottomInParent();
976                         if (icBottomPos + touchOffsetY >= this._bottomBoundary) {
977                             realOffsetY = this._bottomBoundary - icBottomPos;
978                             this.scrollToBottomEvent();
979                             scrollEnabled = false;
980                         }
981                     }
982                     else if (touchOffsetX < 0.0 && touchOffsetY == 0.0) // left
983                     {
984                         var icRightPos = this._innerContainer.getRightInParent();
985                         if (icRightPos + touchOffsetX <= this._rightBoundary) {
986                             realOffsetX = this._rightBoundary - icRightPos;
987                             this.scrollToRightEvent();
988                             scrollEnabled = false;
989                         }
990                     }
991                     else if (touchOffsetX == 0.0 && touchOffsetY < 0) // down
992                     {
993                         var icTopPos = this._innerContainer.getTopInParent();
994                         if (icTopPos + touchOffsetY <= this._topBoundary) {
995                             realOffsetY = this._topBoundary - icTopPos;
996                             this.scrollToTopEvent();
997                             scrollEnabled = false;
998                         }
999                     }
1000                     else if (touchOffsetX > 0 && touchOffsetY == 0) // right
1001                     {
1002                         var icLeftPos = this._innerContainer.getLeftInParent();
1003                         if (icLeftPos + touchOffsetX >= this._leftBoundary) {
1004                             realOffsetX = this._leftBoundary - icLeftPos;
1005                             this.scrollToLeftEvent();
1006                             scrollEnabled = false;
1007                         }
1008                     }
1009                 }
1010                 this.moveChildren(realOffsetX, realOffsetY);
1011                 break;
1012             default:
1013                 break;
1014         }
1015         return scrollEnabled;
1016     },
1017 
1018     scrollToBottom: function (time, attenuated) {
1019         this.startAutoScrollChildrenWithDestination(cc.p(this._innerContainer.getPosition().x, 0), time, attenuated);
1020     },
1021 
1022     scrollToTop: function (time, attenuated) {
1023         this.startAutoScrollChildrenWithDestination(cc.p(this._innerContainer.getPosition().x, this._size.height - this._innerContainer.getSize().height), time, attenuated);
1024     },
1025 
1026     scrollToLeft: function (time, attenuated) {
1027         this.startAutoScrollChildrenWithDestination(cc.p(0, this._innerContainer.getPosition().y), time, attenuated);
1028     },
1029 
1030     scrollToRight: function (time, attenuated) {
1031         this.startAutoScrollChildrenWithDestination(cc.p(this._size.width - this._innerContainer.getSize().width, this._innerContainer.getPosition().y), time, attenuated);
1032     },
1033 
1034     scrollToTopLeft: function (time, attenuated) {
1035         if (this._direction != ccs.ScrollViewDir.both) {
1036             cc.log("Scroll diretion is not both!");
1037             return;
1038         }
1039         this.startAutoScrollChildrenWithDestination(cc.p(0, this._size.height - this._innerContainer.getSize().height), time, attenuated);
1040     },
1041 
1042     scrollToTopRight: function (time, attenuated) {
1043         if (this._direction != ccs.ScrollViewDir.both) {
1044             cc.log("Scroll diretion is not both!");
1045             return;
1046         }
1047         this.startAutoScrollChildrenWithDestination(cc.p(this._size.width - this._innerContainer.getSize().width, this._size.height - this._innerContainer.getSize().height), time, attenuated);
1048     },
1049 
1050     scrollToBottomLeft: function (time, attenuated) {
1051         if (this._direction != ccs.ScrollViewDir.both) {
1052             cc.log("Scroll diretion is not both!");
1053             return;
1054         }
1055         this.startAutoScrollChildrenWithDestination(cc.p(0, 0), time, attenuated);
1056     },
1057 
1058     scrollToBottomRight: function (time, attenuated) {
1059         if (this._direction != ccs.ScrollViewDir.both) {
1060             cc.log("Scroll diretion is not both!");
1061             return;
1062         }
1063         this.startAutoScrollChildrenWithDestination(cc.p(this._size.width - this._innerContainer.getSize().width, 0), time, attenuated);
1064     },
1065 
1066     scrollToPercentVertical: function (percent, time, attenuated) {
1067         var minY = this._size.height - this._innerContainer.getSize().height;
1068         var h = -minY;
1069         this.startAutoScrollChildrenWithDestination(cc.p(this._innerContainer.getPosition().x, minY + percent * h / 100), time, attenuated);
1070     },
1071 
1072     scrollToPercentHorizontal: function (percent, time, attenuated) {
1073         var w = this._innerContainer.getSize().width - this._size.width;
1074         this.startAutoScrollChildrenWithDestination(cc.p(-(percent * w / 100), this._innerContainer.getPosition().y), time, attenuated);
1075     },
1076 
1077     scrollToPercentBothDirection: function (percent, time, attenuated) {
1078         if (this._direction != ccs.ScrollViewDir.both) {
1079             return;
1080         }
1081         var minY = this._size.height - this._innerContainer.getSize().height;
1082         var h = -minY;
1083         var w = this._innerContainer.getSize().width - this._size.width;
1084         this.startAutoScrollChildrenWithDestination(cc.p(-(percent.x * w / 100), minY + percent.y * h / 100), time, attenuated);
1085     },
1086 
1087     jumpToBottom: function () {
1088         this.jumpToDestination(cc.p(this._innerContainer.getPosition().x, 0));
1089     },
1090 
1091     jumpToTop: function () {
1092         this.jumpToDestination(cc.p(this._innerContainer.getPosition().x, this._size.height - this._innerContainer.getSize().height));
1093     },
1094 
1095     jumpToLeft: function () {
1096         this.jumpToDestination(cc.p(0, this._innerContainer.getPosition().y));
1097     },
1098 
1099     jumpToRight: function () {
1100         this.jumpToDestination(cc.p(this._size.width - this._innerContainer.getSize().width, this._innerContainer.getPosition().y));
1101     },
1102 
1103     jumpToTopLeft: function () {
1104         if (this._direction != ccs.ScrollViewDir.both) {
1105             cc.log("Scroll diretion is not both!");
1106             return;
1107         }
1108         this.jumpToDestination(cc.p(0, this._size.height - this._innerContainer.getSize().height));
1109     },
1110 
1111     jumpToTopRight: function () {
1112         if (this._direction != ccs.ScrollViewDir.both) {
1113             cc.log("Scroll diretion is not both!");
1114             return;
1115         }
1116         this.jumpToDestination(cc.p(this._size.width - this._innerContainer.getSize().width, this._size.height - this._innerContainer.getSize().height));
1117     },
1118 
1119     jumpToBottomLeft: function () {
1120         if (this._direction != ccs.ScrollViewDir.both) {
1121             cc.log("Scroll diretion is not both!");
1122             return;
1123         }
1124         this.jumpToDestination(cc.p(0, 0));
1125     },
1126 
1127     jumpToBottomRight: function () {
1128         if (this._direction != ccs.ScrollViewDir.both) {
1129             cc.log("Scroll diretion is not both!");
1130             return;
1131         }
1132         this.jumpToDestination(cc.p(this._size.width - this._innerContainer.getSize().width, 0));
1133     },
1134 
1135     jumpToPercentVertical: function (percent) {
1136         var minY = this._size.height - this._innerContainer.getSize().height;
1137         var h = -minY;
1138         this.jumpToDestination(cc.p(this._innerContainer.getPosition().x, minY + percent * h / 100));
1139     },
1140 
1141     jumpToPercentHorizontal: function (percent) {
1142         var w = this._innerContainer.getSize().width - this._size.width;
1143         this.jumpToDestination(cc.p(-(percent * w / 100), this._innerContainer.getPosition().y));
1144     },
1145 
1146     jumpToPercentBothDirection: function (percent) {
1147         if (this._direction != ccs.ScrollViewDir.both) {
1148             return;
1149         }
1150         var minY = this._size.height - this._innerContainer.getSize().height;
1151         var h = -minY;
1152         var w = this._innerContainer.getSize().width - this._size.width;
1153         this.jumpToDestination(cc.p(-(percent.x * w / 100), minY + percent.y * h / 100));
1154     },
1155 
1156     startRecordSlidAction: function () {
1157         if (this._autoScroll) {
1158             this.stopAutoScrollChildren();
1159         }
1160         if (this._bouncing) {
1161             this.stopBounceChildren();
1162         }
1163         this._slidTime = 0.0;
1164     },
1165 
1166     endRecordSlidAction: function () {
1167         if (!this.checkNeedBounce() && this._inertiaScrollEnabled) {
1168             if (this._slidTime <= 0.016) {
1169                 return;
1170             }
1171             var totalDis = 0;
1172             var dir;
1173             switch (this._direction) {
1174                 case ccs.ScrollViewDir.vertical :
1175                     totalDis = this._touchEndedPoint.y - this._touchBeganPoint.y;
1176                     if (totalDis < 0) {
1177                         dir = ccs.SCROLLDIR_DOWN;
1178                     }
1179                     else {
1180                         dir = ccs.SCROLLDIR_UP;
1181                     }
1182                     break;
1183                 case ccs.ScrollViewDir.horizontal:
1184                     totalDis = this._touchEndedPoint.x - this._touchBeganPoint.x;
1185                     if (totalDis < 0) {
1186                         dir = ccs.SCROLLDIR_LEFT;
1187                     }
1188                     else {
1189                         dir = ccs.SCROLLDIR_RIGHT;
1190                     }
1191                     break;
1192                 case ccs.ScrollViewDir.both :
1193                     var subVector = cc.pSub(this._touchEndedPoint, this._touchBeganPoint);
1194                     totalDis = cc.pLength(subVector);
1195                     dir = cc.pNormalize(subVector);
1196                     break;
1197                 default:
1198                     break;
1199             }
1200             var orSpeed = Math.min(Math.abs(totalDis) / (this._slidTime), ccs.AUTOSCROLLMAXSPEED);
1201             this.startAutoScrollChildrenWithOriginalSpeed(dir, orSpeed, true, -1000);
1202             this._slidTime = 0;
1203         }
1204     },
1205 
1206     handlePressLogic: function (touchPoint) {
1207         this._touchBeganPoint = this._renderer.convertToNodeSpace(touchPoint);
1208         this._touchMovingPoint = this._touchBeganPoint;
1209         this.startRecordSlidAction();
1210         this._bePressed = true;
1211     },
1212 
1213     handleMoveLogic: function (touchPoint) {
1214         this._touchMovedPoint = this._renderer.convertToNodeSpace(touchPoint);
1215         var delta = cc.pSub(this._touchMovedPoint, this._touchMovingPoint);
1216         this._touchMovingPoint = this._touchMovedPoint;
1217         switch (this._direction) {
1218             case ccs.ScrollViewDir.vertical: // vertical
1219                 this.scrollChildren(0.0, delta.y);
1220                 break;
1221             case ccs.ScrollViewDir.horizontal: // horizontal
1222                 this.scrollChildren(delta.x, 0);
1223                 break;
1224             case ccs.ScrollViewDir.both: // both
1225                 this.scrollChildren(delta.x, delta.y);
1226                 break;
1227             default:
1228                 break;
1229         }
1230     },
1231 
1232     handleReleaseLogic: function (touchPoint) {
1233         this._touchEndedPoint = this._renderer.convertToNodeSpace(touchPoint);
1234         this.endRecordSlidAction();
1235         this._bePressed = false;
1236     },
1237 
1238     onTouchBegan: function (touchPoint) {
1239         var pass = ccs.UILayout.prototype.onTouchBegan.call(this, touchPoint);
1240         this.handlePressLogic(touchPoint);
1241         return pass;
1242     },
1243 
1244     onTouchMoved: function (touchPoint) {
1245         ccs.UILayout.prototype.onTouchMoved.call(this, touchPoint);
1246         this.handleMoveLogic(touchPoint);
1247     },
1248 
1249     onTouchEnded: function (touchPoint) {
1250         ccs.UILayout.prototype.onTouchEnded.call(this, touchPoint);
1251         this.handleReleaseLogic(touchPoint);
1252     },
1253 
1254     onTouchCancelled: function (touchPoint) {
1255         ccs.UILayout.prototype.onTouchCancelled.call(this, touchPoint);
1256     },
1257 
1258     onTouchLongClicked: function (touchPoint) {
1259 
1260     },
1261 
1262     update: function (dt) {
1263         if (this._autoScroll) {
1264             this.autoScrollChildren(dt);
1265         }
1266         if (this._bouncing) {
1267             this.bounceChildren(dt);
1268         }
1269         this.recordSlidTime(dt);
1270     },
1271 
1272     recordSlidTime: function (dt) {
1273         if (this._bePressed) {
1274             this._slidTime += dt;
1275         }
1276     },
1277 
1278     /**
1279      * Intercept touch event
1280      * @param {number} handleState
1281      * @param {ccs.UIWidget} sender
1282      * @param {cc.Point} touchPoint
1283      */
1284     interceptTouchEvent: function (handleState, sender, touchPoint) {
1285         switch (handleState) {
1286             case 0:
1287                 this.handlePressLogic(touchPoint);
1288                 break;
1289             case 1:
1290                 var offset = cc.pSub(sender.getTouchStartPos(), touchPoint);
1291                 if (cc.pLength(offset) > this._childFocusCancelOffset) {
1292                     sender.setFocused(false);
1293                     this.handleMoveLogic(touchPoint);
1294                 }
1295                 break;
1296             case 2:
1297                 this.handleReleaseLogic(touchPoint);
1298                 break;
1299             case 3:
1300                 this.handleReleaseLogic(touchPoint);
1301                 break;
1302         }
1303     },
1304 
1305     /**
1306      *
1307      * @param {number} handleState
1308      * @param {ccs.UIWidget} sender
1309      * @param {cc.Point} touchPoint
1310      */
1311     checkChildInfo: function (handleState, sender, touchPoint) {
1312         this.interceptTouchEvent(handleState, sender, touchPoint);
1313     },
1314 
1315     scrollToTopEvent: function () {
1316         if (this._scrollViewEventListener && this._scrollViewEventSelector) {
1317             this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccs.ScrollViewEventType.scrollToTop);
1318         }
1319     },
1320 
1321     scrollToBottomEvent: function () {
1322         if (this._scrollViewEventListener && this._scrollViewEventSelector) {
1323             this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccs.ScrollViewEventType.scrollToBottom);
1324         }
1325     },
1326 
1327     scrollToLeftEvent: function () {
1328         if (this._scrollViewEventListener && this._scrollViewEventSelector) {
1329             this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccs.ScrollViewEventType.scrollToLeft);
1330         }
1331     },
1332 
1333     scrollToRightEvent: function () {
1334         if (this._scrollViewEventListener && this._scrollViewEventSelector) {
1335             this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccs.ScrollViewEventType.scrollToRight);
1336         }
1337     },
1338 
1339     scrollingEvent: function () {
1340         if (this._scrollViewEventListener && this._scrollViewEventSelector) {
1341             this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccs.ScrollViewEventType.scrolling);
1342         }
1343     },
1344 
1345     bounceTopEvent: function () {
1346         if (this._scrollViewEventListener && this._scrollViewEventSelector) {
1347             this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccs.ScrollViewEventType.bounceTop);
1348         }
1349     },
1350 
1351     bounceBottomEvent: function () {
1352         if (this._scrollViewEventListener && this._scrollViewEventSelector) {
1353             this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccs.ScrollViewEventType.bounceBottom);
1354         }
1355     },
1356 
1357     bounceLeftEvent: function () {
1358         if (this._scrollViewEventListener && this._scrollViewEventSelector) {
1359             this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccs.ScrollViewEventType.bounceLeft);
1360         }
1361     },
1362 
1363     bounceRightEvent: function () {
1364         if (this._scrollViewEventListener && this._scrollViewEventSelector) {
1365             this._scrollViewEventSelector.call(this._scrollViewEventListener, this, ccs.ScrollViewEventType.bounceRight);
1366         }
1367     },
1368 
1369     /**
1370      * @param {Function} selector
1371      * @param {Object} target
1372      */
1373     addEventListenerScrollView: function (selector, target) {
1374         this._scrollViewEventSelector = selector;
1375         this._scrollViewEventListener = target;
1376     },
1377 
1378     /**
1379      * set direction
1380      * @param {ccs.ScrollViewDir} dir
1381      */
1382     setDirection: function (dir) {
1383         this._direction = dir;
1384     },
1385 
1386     /**
1387      * get direction
1388      * @returns {ccs.ScrollViewDir}
1389      */
1390     getDirection: function () {
1391         return this._direction;
1392     },
1393 
1394     /**
1395      * set bounce enabled
1396      * @param {Boolean} enabled
1397      */
1398     setBounceEnabled: function (enabled) {
1399         this._bounceEnabled = enabled;
1400     },
1401 
1402     /**
1403      * get whether bounce id enabled
1404      * @returns {boolean}
1405      */
1406     isBounceEnabled: function () {
1407         return this._bounceEnabled;
1408     },
1409 
1410     /**
1411      * set inertiaScroll enabled
1412      * @param {boolean} enabled
1413      */
1414     setInertiaScrollEnabled: function (enabled) {
1415         this._inertiaScrollEnabled = enabled;
1416     },
1417 
1418     /**
1419      * get whether inertiaScroll id enabled
1420      * @returns {boolean}
1421      */
1422     isInertiaScrollEnabled: function () {
1423         return this._inertiaScrollEnabled;
1424     },
1425 
1426     /**
1427      * get inner container
1428      * @returns {ccs.UILayout}
1429      */
1430     getInnerContainer: function () {
1431         return this._innerContainer;
1432     },
1433 
1434     /**
1435      * Sets LayoutType.
1436      * @param {ccs.LayoutType} type
1437      */
1438     setLayoutType: function (type) {
1439         this._innerContainer.setLayoutType(type);
1440     },
1441 
1442     /**
1443      * Gets LayoutType.
1444      * @returns {ccs.LayoutType}
1445      */
1446     getLayoutType: function () {
1447         return this._innerContainer.getLayoutType();
1448     },
1449 
1450     doLayout: function () {
1451         this._innerContainer.doLayout();
1452     },
1453 
1454     /**
1455      * Returns the "class name" of widget.
1456      * @returns {string}
1457      */
1458     getDescription: function () {
1459         return "ScrollView";
1460     },
1461 
1462     copyClonedWidgetChildren: function (model) {
1463         ccs.UILayout.prototype.copyClonedWidgetChildren.call(this, model);
1464     },
1465 
1466     copySpecialProperties: function (scrollView) {
1467         ccs.UILayout.prototype.copySpecialProperties.call(this, scrollView);
1468         this.setInnerContainerSize(scrollView.getInnerContainerSize());
1469         this.setDirection(scrollView._direction);
1470         this.setBounceEnabled(scrollView._bounceEnabled);
1471         this.setInertiaScrollEnabled(scrollView._inertiaScrollEnabled);
1472     }
1473 });
1474 /**
1475  * allocates and initializes a UIScrollView.
1476  * @constructs
1477  * @return {ccs.UIScrollView}
1478  * @example
1479  * // example
1480  * var uiScrollView = ccs.UIScrollView.create();
1481  */
1482 ccs.UIScrollView.create = function () {
1483     var uiScrollView = new ccs.UIScrollView();
1484     if (uiScrollView && uiScrollView.init()) {
1485         return uiScrollView;
1486     }
1487     return null;
1488 };