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