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