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