1 /**************************************************************************** 2 Copyright (c) 2008-2010 Ricardo Quesada 3 Copyright (c) 2011-2012 cocos2d-x.org 4 Copyright (c) 2013-2014 Chukong Technologies Inc. 5 Copyright (c) 2010 Sangwoo Im 6 7 http://www.cocos2d-x.org 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ****************************************************************************/ 27 28 /** 29 * The constant value of the fill style from top to bottom for cc.TableView 30 * @constant 31 * @type {number} 32 */ 33 cc.TABLEVIEW_FILL_TOPDOWN = 0; 34 35 /** 36 * The constant value of the fill style from bottom to top for cc.TableView 37 * @constant 38 * @type {number} 39 */ 40 cc.TABLEVIEW_FILL_BOTTOMUP = 1; 41 42 /** 43 * Abstract class for SWTableView cell node 44 * @class 45 * @abstract 46 * @extends cc.Node 47 * 48 * @property {Number} objectId - The index used internally by SWTableView and its subclasses 49 */ 50 cc.TableViewCell = cc.Node.extend(/** @lends cc.TableViewCell# */{ 51 _idx:0, 52 _className:"TableViewCell", 53 54 /** 55 * The index used internally by SWTableView and its subclasses 56 */ 57 getIdx:function () { 58 return this._idx; 59 }, 60 setIdx:function (idx) { 61 this._idx = idx; 62 }, 63 64 /** 65 * Cleans up any resources linked to this cell and resets <code>idx</code> property. 66 */ 67 reset:function () { 68 this._idx = cc.INVALID_INDEX; 69 }, 70 71 setObjectID:function (idx) { 72 this._idx = idx; 73 }, 74 getObjectID:function () { 75 return this._idx; 76 } 77 }); 78 79 var _p = cc.TableViewCell.prototype; 80 81 /** @expose */ 82 _p.objectId; 83 cc.defineGetterSetter(_p, "objectId", _p.getObjectID, _p.setObjectID); 84 85 _p = null; 86 87 /** 88 * Sole purpose of this delegate is to single touch event in this version. 89 */ 90 cc.TableViewDelegate = cc.ScrollViewDelegate.extend(/** @lends cc.TableViewDelegate# */{ 91 /** 92 * Delegate to respond touch event 93 * 94 * @param {cc.TableView} table table contains the given cell 95 * @param {cc.TableViewCell} cell cell that is touched 96 */ 97 tableCellTouched:function (table, cell) { 98 }, 99 100 /** 101 * Delegate to respond a table cell press event. 102 * 103 * @param {cc.TableView} table table contains the given cell 104 * @param {cc.TableViewCell} cell cell that is pressed 105 */ 106 tableCellHighlight:function(table, cell){ 107 }, 108 109 /** 110 * Delegate to respond a table cell release event 111 * 112 * @param {cc.TableView} table table contains the given cell 113 * @param {cc.TableViewCell} cell cell that is pressed 114 */ 115 tableCellUnhighlight:function(table, cell){ 116 117 }, 118 119 /** 120 * <p> 121 * Delegate called when the cell is about to be recycled. Immediately <br/> 122 * after this call the cell will be removed from the scene graph and <br/> 123 * recycled. 124 * </p> 125 * @param table table contains the given cell 126 * @param cell cell that is pressed 127 */ 128 tableCellWillRecycle:function(table, cell){ 129 130 } 131 }); 132 133 /** 134 * Data source that governs table backend data. 135 */ 136 cc.TableViewDataSource = cc.Class.extend(/** @lends cc.TableViewDataSource# */{ 137 /** 138 * cell size for a given index 139 * @param {cc.TableView} table table to hold the instances of Class 140 * @param {Number} idx the index of a cell to get a size 141 * @return {cc.Size} size of a cell at given index 142 */ 143 tableCellSizeForIndex:function(table, idx){ 144 return this.cellSizeForTable(table); 145 }, 146 /** 147 * cell height for a given table. 148 * 149 * @param {cc.TableView} table table to hold the instances of Class 150 * @return {cc.Size} cell size 151 */ 152 cellSizeForTable:function (table) { 153 return cc.size(0,0); 154 }, 155 156 /** 157 * a cell instance at a given index 158 * @param {cc.TableView} table table to hold the instances of Class 159 * @param idx index to search for a cell 160 * @return {cc.TableView} cell found at idx 161 */ 162 tableCellAtIndex:function (table, idx) { 163 return null; 164 }, 165 166 /** 167 * Returns number of cells in a given table view. 168 * @param {cc.TableView} table table to hold the instances of Class 169 * @return {Number} number of cells 170 */ 171 numberOfCellsInTableView:function (table) { 172 return 0; 173 } 174 }); 175 176 /** 177 * UITableView counterpart for cocos2d for iphone. 178 * this is a very basic, minimal implementation to bring UITableView-like component into cocos2d world. 179 * 180 * @class 181 * @extends cc.ScrollView 182 * 183 * @property {cc.TableViewDataSource} dataSource - The data source of the table view 184 * @property {cc.TableViewDelegate} delegate - The event delegate of the table view 185 * @property {Number} verticalFillOrder - The index to determine how cell is ordered and filled in the view 186 * 187 */ 188 cc.TableView = cc.ScrollView.extend(/** @lends cc.TableView# */{ 189 _vOrdering:null, 190 _indices:null, 191 _cellsFreed:null, 192 _dataSource:null, 193 _tableViewDelegate:null, 194 _oldDirection:null, 195 _cellsPositions:null, //vector with all cell positions 196 _touchedCell:null, 197 198 /** 199 * The 200 * @param dataSource 201 * @param size 202 * @param container 203 */ 204 ctor:function (dataSource, size, container) { 205 cc.ScrollView.prototype.ctor.call(this); 206 this._oldDirection = cc.SCROLLVIEW_DIRECTION_NONE; 207 this._cellsPositions = []; 208 209 this.initWithViewSize(size, container); 210 this.setDataSource(dataSource); 211 this._updateCellPositions(); 212 this._updateContentSize(); 213 }, 214 215 __indexFromOffset:function (offset) { 216 var low = 0; 217 var high = this._dataSource.numberOfCellsInTableView(this) - 1; 218 var search; 219 switch (this.getDirection()) { 220 case cc.SCROLLVIEW_DIRECTION_HORIZONTAL: 221 search = offset.x; 222 break; 223 default: 224 search = offset.y; 225 break; 226 } 227 228 var locCellsPositions = this._cellsPositions; 229 while (high >= low){ 230 var index = 0|(low + (high - low) / 2); 231 var cellStart = locCellsPositions[index]; 232 var cellEnd = locCellsPositions[index + 1]; 233 234 if (search >= cellStart && search <= cellEnd){ 235 return index; 236 } else if (search < cellStart){ 237 high = index - 1; 238 }else { 239 low = index + 1; 240 } 241 } 242 243 if (low <= 0) 244 return 0; 245 return -1; 246 }, 247 248 _indexFromOffset:function (offset) { 249 var locOffset = {x: offset.x, y: offset.y}; 250 var locDataSource = this._dataSource; 251 var maxIdx = locDataSource.numberOfCellsInTableView(this) - 1; 252 253 if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN) 254 locOffset.y = this.getContainer().getContentSize().height - locOffset.y; 255 256 var index = this.__indexFromOffset(locOffset); 257 if (index !== -1) { 258 index = Math.max(0, index); 259 if (index > maxIdx) 260 index = cc.INVALID_INDEX; 261 } 262 return index; 263 }, 264 265 __offsetFromIndex:function (index) { 266 var offset; 267 switch (this.getDirection()) { 268 case cc.SCROLLVIEW_DIRECTION_HORIZONTAL: 269 offset = cc.p(this._cellsPositions[index], 0); 270 break; 271 default: 272 offset = cc.p(0, this._cellsPositions[index]); 273 break; 274 } 275 276 return offset; 277 }, 278 279 _offsetFromIndex:function (index) { 280 var offset = this.__offsetFromIndex(index); 281 282 var cellSize = this._dataSource.tableCellSizeForIndex(this, index); 283 if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN) 284 offset.y = this.getContainer().getContentSize().height - offset.y - cellSize.height; 285 286 return offset; 287 }, 288 289 _updateCellPositions:function(){ 290 var cellsCount = this._dataSource.numberOfCellsInTableView(this); 291 var locCellsPositions = this._cellsPositions; 292 293 if (cellsCount > 0){ 294 var currentPos = 0; 295 var cellSize, locDataSource = this._dataSource; 296 for (var i=0; i < cellsCount; i++) { 297 locCellsPositions[i] = currentPos; 298 cellSize = locDataSource.tableCellSizeForIndex(this, i); 299 switch (this.getDirection()) { 300 case cc.SCROLLVIEW_DIRECTION_HORIZONTAL: 301 currentPos += cellSize.width; 302 break; 303 default: 304 currentPos += cellSize.height; 305 break; 306 } 307 } 308 this._cellsPositions[cellsCount] = currentPos;//1 extra value allows us to get right/bottom of the last cell 309 } 310 }, 311 312 _updateContentSize:function () { 313 var size = cc.size(0, 0); 314 315 var cellsCount = this._dataSource.numberOfCellsInTableView(this); 316 317 if(cellsCount > 0){ 318 var maxPosition = this._cellsPositions[cellsCount]; 319 switch (this.getDirection()) { 320 case cc.SCROLLVIEW_DIRECTION_HORIZONTAL: 321 size = cc.size(maxPosition, this._viewSize.height); 322 break; 323 default: 324 size = cc.size(this._viewSize.width, maxPosition); 325 break; 326 } 327 } 328 329 this.setContentSize(size); 330 331 if (this._oldDirection !== this._direction) { 332 if (this._direction === cc.SCROLLVIEW_DIRECTION_HORIZONTAL) { 333 this.setContentOffset(cc.p(0, 0)); 334 } else { 335 this.setContentOffset(cc.p(0, this.minContainerOffset().y)); 336 } 337 this._oldDirection = this._direction; 338 } 339 }, 340 341 _moveCellOutOfSight:function (cell) { 342 if(this._tableViewDelegate && this._tableViewDelegate.tableCellWillRecycle) 343 this._tableViewDelegate.tableCellWillRecycle(this, cell); 344 345 this._cellsFreed.addObject(cell); 346 this._cellsUsed.removeSortedObject(cell); 347 cc.arrayRemoveObject(this._indices, cell.getIdx()); 348 349 cell.reset(); 350 if (cell.getParent() === this.getContainer()) { 351 this.getContainer().removeChild(cell, true); 352 } 353 }, 354 355 _setIndexForCell:function (index, cell) { 356 cell.setAnchorPoint(0, 0); 357 cell.setPosition(this._offsetFromIndex(index)); 358 cell.setIdx(index); 359 }, 360 361 _addCellIfNecessary:function (cell) { 362 if (cell.getParent() !== this.getContainer()) { 363 this.getContainer().addChild(cell); 364 } 365 this._cellsUsed.insertSortedObject(cell); 366 var locIndices = this._indices, addIdx = cell.getIdx(); 367 if(locIndices.indexOf(addIdx) === -1){ 368 locIndices.push(addIdx); 369 //sort 370 locIndices.sort(function(a,b){return a-b;}); 371 } 372 }, 373 374 /** 375 * data source 376 */ 377 getDataSource:function () { 378 return this._dataSource; 379 }, 380 setDataSource:function (source) { 381 this._dataSource = source; 382 }, 383 384 /** 385 * delegate 386 */ 387 getDelegate:function () { 388 return this._tableViewDelegate; 389 }, 390 391 setDelegate:function (delegate) { 392 this._tableViewDelegate = delegate; 393 }, 394 395 /** 396 * determines how cell is ordered and filled in the view. 397 */ 398 setVerticalFillOrder:function (fillOrder) { 399 if (this._vOrdering !== fillOrder) { 400 this._vOrdering = fillOrder; 401 if (this._cellsUsed.count() > 0) { 402 this.reloadData(); 403 } 404 } 405 }, 406 getVerticalFillOrder:function () { 407 return this._vOrdering; 408 }, 409 410 initWithViewSize:function (size, container) { 411 if (cc.ScrollView.prototype.initWithViewSize.call(this, size, container)) { 412 this._cellsUsed = new cc.ArrayForObjectSorting(); 413 this._cellsFreed = new cc.ArrayForObjectSorting(); 414 this._indices = []; 415 this._tableViewDelegate = null; 416 this._vOrdering = cc.TABLEVIEW_FILL_BOTTOMUP; 417 this.setDirection(cc.SCROLLVIEW_DIRECTION_VERTICAL); 418 419 cc.ScrollView.prototype.setDelegate.call(this, this); 420 return true; 421 } 422 return false; 423 }, 424 425 /** 426 * Updates the content of the cell at a given index. 427 * 428 * @param idx index to find a cell 429 */ 430 updateCellAtIndex:function (idx) { 431 if (idx === cc.INVALID_INDEX || idx > this._dataSource.numberOfCellsInTableView(this) - 1) 432 return; 433 434 var cell = this.cellAtIndex(idx); 435 if (cell) 436 this._moveCellOutOfSight(cell); 437 438 cell = this._dataSource.tableCellAtIndex(this, idx); 439 this._setIndexForCell(idx, cell); 440 this._addCellIfNecessary(cell); 441 }, 442 443 /** 444 * Inserts a new cell at a given index 445 * 446 * @param idx location to insert 447 */ 448 insertCellAtIndex:function (idx) { 449 if (idx === cc.INVALID_INDEX || idx > this._dataSource.numberOfCellsInTableView(this) - 1) 450 return; 451 452 var newIdx, locCellsUsed = this._cellsUsed; 453 var cell = locCellsUsed.objectWithObjectID(idx); 454 if (cell) { 455 newIdx = locCellsUsed.indexOfSortedObject(cell); 456 for (var i = newIdx; i < locCellsUsed.count(); i++) { 457 cell = locCellsUsed.objectAtIndex(i); 458 this._setIndexForCell(cell.getIdx() + 1, cell); 459 } 460 } 461 462 //insert a new cell 463 cell = this._dataSource.tableCellAtIndex(this, idx); 464 this._setIndexForCell(idx, cell); 465 this._addCellIfNecessary(cell); 466 467 this._updateCellPositions(); 468 this._updateContentSize(); 469 }, 470 471 /** 472 * Removes a cell at a given index 473 * 474 * @param idx index to find a cell 475 */ 476 removeCellAtIndex:function (idx) { 477 if (idx === cc.INVALID_INDEX || idx > this._dataSource.numberOfCellsInTableView(this) - 1) 478 return; 479 480 var cell = this.cellAtIndex(idx); 481 if (!cell) 482 return; 483 484 var locCellsUsed = this._cellsUsed; 485 var newIdx = locCellsUsed.indexOfSortedObject(cell); 486 487 //remove first 488 this._moveCellOutOfSight(cell); 489 cc.arrayRemoveObject(this._indices, idx); 490 this._updateCellPositions(); 491 492 for (var i = locCellsUsed.count() - 1; i > newIdx; i--) { 493 cell = locCellsUsed.objectAtIndex(i); 494 this._setIndexForCell(cell.getIdx() - 1, cell); 495 } 496 }, 497 498 /** 499 * reloads data from data source. the view will be refreshed. 500 */ 501 reloadData:function () { 502 this._oldDirection = cc.SCROLLVIEW_DIRECTION_NONE; 503 var locCellsUsed = this._cellsUsed, locCellsFreed = this._cellsFreed, locContainer = this.getContainer(); 504 for (var i = 0, len = locCellsUsed.count(); i < len; i++) { 505 var cell = locCellsUsed.objectAtIndex(i); 506 507 if(this._tableViewDelegate && this._tableViewDelegate.tableCellWillRecycle) 508 this._tableViewDelegate.tableCellWillRecycle(this, cell); 509 510 locCellsFreed.addObject(cell); 511 cell.reset(); 512 if (cell.getParent() === locContainer) 513 locContainer.removeChild(cell, true); 514 } 515 516 this._indices = []; 517 this._cellsUsed = new cc.ArrayForObjectSorting(); 518 519 this._updateCellPositions(); 520 this._updateContentSize(); 521 if (this._dataSource.numberOfCellsInTableView(this) > 0) 522 this.scrollViewDidScroll(this); 523 524 this.setNodeDirty(); 525 }, 526 527 /** 528 * Dequeues a free cell if available. nil if not. 529 * 530 * @return {TableViewCell} free cell 531 */ 532 dequeueCell:function () { 533 if (this._cellsFreed.count() === 0) { 534 return null; 535 } else { 536 var cell = this._cellsFreed.objectAtIndex(0); 537 this._cellsFreed.removeObjectAtIndex(0); 538 return cell; 539 } 540 }, 541 542 /** 543 * Returns an existing cell at a given index. Returns nil if a cell is nonexistent at the moment of query. 544 * 545 * @param idx index 546 * @return {cc.TableViewCell} a cell at a given index 547 */ 548 cellAtIndex:function (idx) { 549 var i = this._indices.indexOf(idx); 550 if (i === -1) 551 return null; 552 return this._cellsUsed.objectWithObjectID(idx); 553 }, 554 555 scrollViewDidScroll:function (view) { 556 var locDataSource = this._dataSource; 557 var countOfItems = locDataSource.numberOfCellsInTableView(this); 558 if (0 === countOfItems) 559 return; 560 561 if (this._tableViewDelegate !== null && this._tableViewDelegate.scrollViewDidScroll) 562 this._tableViewDelegate.scrollViewDidScroll(this); 563 564 var idx = 0, locViewSize = this._viewSize, locContainer = this.getContainer(); 565 var offset = this.getContentOffset(); 566 offset.x *= -1; 567 offset.y *= -1; 568 569 var maxIdx = Math.max(countOfItems-1, 0); 570 571 if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN) 572 offset.y = offset.y + locViewSize.height/locContainer.getScaleY(); 573 var startIdx = this._indexFromOffset(offset); 574 if (startIdx === cc.INVALID_INDEX) 575 startIdx = countOfItems - 1; 576 577 if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN) 578 offset.y -= locViewSize.height/locContainer.getScaleY(); 579 else 580 offset.y += locViewSize.height/locContainer.getScaleY(); 581 offset.x += locViewSize.width/locContainer.getScaleX(); 582 583 var endIdx = this._indexFromOffset(offset); 584 if (endIdx === cc.INVALID_INDEX) 585 endIdx = countOfItems - 1; 586 587 var cell, locCellsUsed = this._cellsUsed; 588 if (locCellsUsed.count() > 0) { 589 cell = locCellsUsed.objectAtIndex(0); 590 idx = cell.getIdx(); 591 while (idx < startIdx) { 592 this._moveCellOutOfSight(cell); 593 if (locCellsUsed.count() > 0) { 594 cell = locCellsUsed.objectAtIndex(0); 595 idx = cell.getIdx(); 596 } else 597 break; 598 } 599 } 600 601 if (locCellsUsed.count() > 0) { 602 cell = locCellsUsed.lastObject(); 603 idx = cell.getIdx(); 604 while (idx <= maxIdx && idx > endIdx) { 605 this._moveCellOutOfSight(cell); 606 if (locCellsUsed.count() > 0) { 607 cell = locCellsUsed.lastObject(); 608 idx = cell.getIdx(); 609 } else 610 break; 611 } 612 } 613 614 var locIndices = this._indices; 615 for (var i = startIdx; i <= endIdx; i++) { 616 if (locIndices.indexOf(i) !== -1) 617 continue; 618 this.updateCellAtIndex(i); 619 } 620 }, 621 622 scrollViewDidZoom:function (view) { 623 }, 624 625 onTouchEnded:function (touch, event) { 626 if (!this.isVisible()) 627 return; 628 629 if (this._touchedCell){ 630 var bb = this.getBoundingBox(); 631 var tmpOrigin = cc.p(bb.x, bb.y); 632 tmpOrigin = this._parent.convertToWorldSpace(tmpOrigin); 633 bb.x = tmpOrigin.x; 634 bb.y = tmpOrigin.y; 635 var locTableViewDelegate = this._tableViewDelegate; 636 if (cc.rectContainsPoint(bb, touch.getLocation()) && locTableViewDelegate !== null){ 637 if(locTableViewDelegate.tableCellUnhighlight) 638 locTableViewDelegate.tableCellUnhighlight(this, this._touchedCell); 639 if(locTableViewDelegate.tableCellTouched) 640 locTableViewDelegate.tableCellTouched(this, this._touchedCell); 641 } 642 this._touchedCell = null; 643 } 644 cc.ScrollView.prototype.onTouchEnded.call(this, touch, event); 645 }, 646 647 onTouchBegan:function(touch, event){ 648 for (var c = this; c != null; c = c.parent) { 649 if (!c.isVisible()) 650 return false; 651 } 652 653 var touchResult = cc.ScrollView.prototype.onTouchBegan.call(this, touch, event); 654 655 if(this._touches.length === 1) { 656 var index, point; 657 658 point = this.getContainer().convertTouchToNodeSpace(touch); 659 660 index = this._indexFromOffset(point); 661 if (index === cc.INVALID_INDEX) 662 this._touchedCell = null; 663 else 664 this._touchedCell = this.cellAtIndex(index); 665 666 if (this._touchedCell && this._tableViewDelegate !== null && this._tableViewDelegate.tableCellHighlight) 667 this._tableViewDelegate.tableCellHighlight(this, this._touchedCell); 668 } else if(this._touchedCell) { 669 if(this._tableViewDelegate !== null && this._tableViewDelegate.tableCellUnhighlight) 670 this._tableViewDelegate.tableCellUnhighlight(this, this._touchedCell); 671 this._touchedCell = null; 672 } 673 674 return touchResult; 675 }, 676 677 onTouchMoved: function(touch, event){ 678 cc.ScrollView.prototype.onTouchMoved.call(this, touch, event); 679 680 if (this._touchedCell && this.isTouchMoved()) { 681 if(this._tableViewDelegate !== null && this._tableViewDelegate.tableCellUnhighlight) 682 this._tableViewDelegate.tableCellUnhighlight(this, this._touchedCell); 683 this._touchedCell = null; 684 } 685 }, 686 687 onTouchCancelled: function(touch, event){ 688 cc.ScrollView.prototype.onTouchCancelled.call(this, touch, event); 689 690 if (this._touchedCell) { 691 if(this._tableViewDelegate !== null && this._tableViewDelegate.tableCellUnhighlight) 692 this._tableViewDelegate.tableCellUnhighlight(this, this._touchedCell); 693 this._touchedCell = null; 694 } 695 } 696 }); 697 698 var _p = cc.TableView.prototype; 699 700 /** @expose */ 701 _p.dataSource; 702 cc.defineGetterSetter(_p, "dataSource", _p.getDataSource, _p.setDataSource); 703 /** @expose */ 704 _p.delegate; 705 cc.defineGetterSetter(_p, "delegate", _p.getDelegate, _p.setDelegate); 706 /** @expose */ 707 _p.verticalFillOrder; 708 cc.defineGetterSetter(_p, "verticalFillOrder", _p.getVerticalFillOrder, _p.setVerticalFillOrder); 709 710 _p = null; 711 712 /** 713 * An initialized table view object 714 * @deprecated 715 * @param {cc.TableViewDataSource} dataSource data source; 716 * @param {cc.Size} size view size 717 * @param {cc.Node} [container] parent object for cells 718 * @return {cc.TableView} table view 719 */ 720 cc.TableView.create = function (dataSource, size, container) { 721 return new cc.TableView(dataSource, size, container); 722 }; 723