1 /**************************************************************************** 2 Copyright (c) 2011-2012 cocos2d-x.org 3 Copyright (c) 2013-2014 Chukong Technologies Inc. 4 5 http://www.cocos2d-x.org 6 7 Permission is hereby granted, free of charge, to any person obtaining a copy 8 of this software and associated documentation files (the "Software"), to deal 9 in the Software without restriction, including without limitation the rights 10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 copies of the Software, and to permit persons to whom the Software is 12 furnished to do so, subject to the following conditions: 13 14 The above copyright notice and this permission notice shall be included in 15 all copies or substantial portions of the Software. 16 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 THE SOFTWARE. 24 ****************************************************************************/ 25 26 /** 27 * ccui.RichElement is the base class of RichElementText, RichElementImage etc. It has type, tag, color and opacity attributes. 28 * @class 29 * @extends ccui.Class 30 */ 31 ccui.RichElement = ccui.Class.extend(/** @lends ccui.RichElement# */{ 32 _type: 0, 33 _tag: 0, 34 _color: null, 35 _opacity:0, 36 /** 37 * Constructor of ccui.RichElement 38 */ 39 ctor: function (tag, color, opacity) { 40 this._type = 0; 41 this._tag = tag || 0; 42 this._color = cc.color(255, 255, 255, 255); 43 if (color) { 44 this._color.r = color.r; 45 this._color.g = color.g; 46 this._color.b = color.b; 47 } 48 this._opacity = opacity || 0; 49 if(opacity === undefined) { 50 this._color.a = color.a; 51 } 52 else { 53 this._color.a = opacity; 54 } 55 } 56 }); 57 58 /** 59 * The text element for RichText, it has text, fontName, fontSize attributes. 60 * @class 61 * @extends ccui.RichElement 62 */ 63 ccui.RichElementText = ccui.RichElement.extend(/** @lends ccui.RichElementText# */{ 64 _text: "", 65 _fontName: "", 66 _fontSize: 0, 67 /** @type cc.FontDefinition */ 68 _fontDefinition: null, 69 /** 70 * Usage Example using FontDefinition: 71 * 72 * var rtEl = new ccui.RichElementText("tag", new cc.FontDefinition({ 73 * fillStyle: cc.color.BLACK, 74 * fontName: "Arial", 75 * fontSize: 12, 76 * fontWeight: "bold", 77 * fontStyle: "normal", 78 * lineHeight: 14 79 * }), 255, "Some Text"); 80 * 81 * Constructor of ccui.RichElementText 82 * @param {Number} tag 83 * @param {cc.Color|cc.FontDefinition} colorOrFontDef 84 * @param {Number} opacity 85 * @param {String} text 86 * @param {String} fontName 87 * @param {Number} fontSize 88 */ 89 ctor: function (tag, colorOrFontDef, opacity, text, fontName, fontSize) { 90 var color = colorOrFontDef; 91 if (colorOrFontDef && colorOrFontDef instanceof cc.FontDefinition) { 92 color = colorOrFontDef.fillStyle; 93 fontName = colorOrFontDef.fontName; 94 fontSize = colorOrFontDef.fontSize; 95 this._fontDefinition = colorOrFontDef; 96 } 97 ccui.RichElement.prototype.ctor.call(this, tag, color, opacity); 98 this._type = ccui.RichElement.TEXT; 99 this._text = text; 100 this._fontName = fontName; 101 this._fontSize = fontSize; 102 } 103 }); 104 105 /** 106 * Create a richElementText 107 * @deprecated since v3.0, please use new ccui.RichElementText() instead. 108 * @param {Number} tag 109 * @param {cc.Color} color 110 * @param {Number} opacity 111 * @param {String} text 112 * @param {String} fontName 113 * @param {Number} fontSize 114 * @returns {ccui.RichElementText} 115 */ 116 ccui.RichElementText.create = function (tag, color, opacity, text, fontName, fontSize) { 117 return new ccui.RichElementText(tag, color, opacity, text, fontName, fontSize); 118 }; 119 120 /** 121 * The image element for RichText, it has filePath, textureRect, textureType attributes. 122 * @class 123 * @extends ccui.RichElement 124 */ 125 ccui.RichElementImage = ccui.RichElement.extend(/** @lends ccui.RichElementImage# */{ 126 _filePath: "", 127 _textureRect: null, 128 _textureType: 0, 129 130 /** 131 * Constructor of ccui.RichElementImage 132 * @param {Number} tag 133 * @param {cc.Color} color 134 * @param {Number} opacity 135 * @param {String} filePath 136 */ 137 ctor: function (tag, color, opacity, filePath) { 138 ccui.RichElement.prototype.ctor.call(this, tag, color, opacity); 139 this._type = ccui.RichElement.IMAGE; 140 this._filePath = filePath || ""; 141 this._textureRect = cc.rect(0, 0, 0, 0); 142 this._textureType = 0; 143 } 144 }); 145 146 /** 147 * Create a richElementImage 148 * @deprecated since v3.0, please use new ccui.RichElementImage() instead. 149 * @param {Number} tag 150 * @param {cc.Color} color 151 * @param {Number} opacity 152 * @param {String} filePath 153 * @returns {ccui.RichElementImage} 154 */ 155 ccui.RichElementImage.create = function (tag, color, opacity, filePath) { 156 return new ccui.RichElementImage(tag, color, opacity, filePath); 157 }; 158 159 /** 160 * The custom node element for RichText. 161 * @class 162 * @extends ccui.RichElement 163 */ 164 ccui.RichElementCustomNode = ccui.RichElement.extend(/** @lends ccui.RichElementCustomNode# */{ 165 _customNode: null, 166 167 /** 168 * Constructor of ccui.RichElementCustomNode 169 * @param {Number} tag 170 * @param {cc.Color} color 171 * @param {Number} opacity 172 * @param {cc.Node} customNode 173 */ 174 ctor: function (tag, color, opacity, customNode) { 175 ccui.RichElement.prototype.ctor.call(this, tag, color, opacity); 176 this._type = ccui.RichElement.CUSTOM; 177 this._customNode = customNode || null; 178 } 179 }); 180 181 /** 182 * Create a richElementCustomNode 183 * @deprecated since v3.0, please use new ccui.RichElementCustomNode() instead. 184 * @param {Number} tag 185 * @param {Number} color 186 * @param {Number} opacity 187 * @param {cc.Node} customNode 188 * @returns {ccui.RichElementCustomNode} 189 */ 190 ccui.RichElementCustomNode.create = function (tag, color, opacity, customNode) { 191 return new ccui.RichElementCustomNode(tag, color, opacity, customNode); 192 }; 193 194 /** 195 * The rich text control of Cocos UI. It receives text, image, and custom node as its children to display. 196 * @class 197 * @extends ccui.Widget 198 */ 199 ccui.RichText = ccui.Widget.extend(/** @lends ccui.RichText# */{ 200 _formatTextDirty: false, 201 _richElements: null, 202 _elementRenders: null, 203 _leftSpaceWidth: 0, 204 _verticalSpace: 0, 205 _elementRenderersContainer: null, 206 _lineBreakOnSpace: false, 207 _textHorizontalAlignment: null, 208 _textVerticalAlignment: null, 209 210 /** 211 * create a rich text 212 * Constructor of ccui.RichText. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function. 213 * @example 214 * var uiRichText = new ccui.RichTex(); 215 */ 216 ctor: function () { 217 ccui.Widget.prototype.ctor.call(this); 218 this._formatTextDirty = false; 219 this._richElements = []; 220 this._elementRenders = []; 221 this._leftSpaceWidth = 0; 222 this._verticalSpace = 0; 223 this._textHorizontalAlignment = cc.TEXT_ALIGNMENT_LEFT; 224 this._textVerticalAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP; 225 }, 226 227 _initRenderer: function () { 228 this._elementRenderersContainer = new cc.Node(); 229 this._elementRenderersContainer.setAnchorPoint(0.5, 0.5); 230 this.addProtectedChild(this._elementRenderersContainer, 0, -1); 231 }, 232 233 /** 234 * Insert a element 235 * @param {ccui.RichElement} element 236 * @param {Number} index 237 */ 238 insertElement: function (element, index) { 239 this._richElements.splice(index, 0, element); 240 this._formatTextDirty = true; 241 }, 242 243 /** 244 * Push a element 245 * @param {ccui.RichElement} element 246 */ 247 pushBackElement: function (element) { 248 this._richElements.push(element); 249 this._formatTextDirty = true; 250 }, 251 252 /** 253 * Remove element 254 * @param {ccui.RichElement} element 255 */ 256 removeElement: function (element) { 257 if (cc.isNumber(element)) 258 this._richElements.splice(element, 1); 259 else 260 cc.arrayRemoveObject(this._richElements, element); 261 this._formatTextDirty = true; 262 }, 263 264 /** 265 * Formats the richText's content. 266 */ 267 formatText: function () { 268 if (this._formatTextDirty) { 269 this._elementRenderersContainer.removeAllChildren(); 270 this._elementRenders.length = 0; 271 var i, element, locRichElements = this._richElements; 272 if (this._ignoreSize) { 273 this._addNewLine(); 274 for (i = 0; i < locRichElements.length; i++) { 275 element = locRichElements[i]; 276 var elementRenderer = null; 277 switch (element._type) { 278 case ccui.RichElement.TEXT: 279 if( element._fontDefinition) 280 elementRenderer = new cc.LabelTTF(element._text, element._fontDefinition); 281 else //todo: There may be ambiguous 282 elementRenderer = new cc.LabelTTF(element._text, element._fontName, element._fontSize); 283 break; 284 case ccui.RichElement.IMAGE: 285 elementRenderer = new cc.Sprite(element._filePath); 286 break; 287 case ccui.RichElement.CUSTOM: 288 elementRenderer = element._customNode; 289 break; 290 default: 291 break; 292 } 293 elementRenderer.setColor(element._color); 294 elementRenderer.setOpacity(element._color.a); 295 this._pushToContainer(elementRenderer); 296 } 297 } else { 298 this._addNewLine(); 299 for (i = 0; i < locRichElements.length; i++) { 300 element = locRichElements[i]; 301 switch (element._type) { 302 case ccui.RichElement.TEXT: 303 if( element._fontDefinition) 304 this._handleTextRenderer(element._text, element._fontDefinition, element._fontDefinition.fontSize, element._fontDefinition.fillStyle); 305 else 306 this._handleTextRenderer(element._text, element._fontName, element._fontSize, element._color); 307 break; 308 case ccui.RichElement.IMAGE: 309 this._handleImageRenderer(element._filePath, element._color, element._color.a); 310 break; 311 case ccui.RichElement.CUSTOM: 312 this._handleCustomRenderer(element._customNode); 313 break; 314 default: 315 break; 316 } 317 } 318 } 319 this.formatRenderers(); 320 this._formatTextDirty = false; 321 } 322 }, 323 /** 324 * Prepare the child LabelTTF based on line breaking 325 * @param {String} text 326 * @param {String|cc.FontDefinition} fontNameOrFontDef 327 * @param {Number} fontSize 328 * @param {cc.Color} color 329 * @private 330 */ 331 _handleTextRenderer: function (text, fontNameOrFontDef, fontSize, color) { 332 if(text === "") 333 return; 334 335 if(text === "\n"){ //Force Line Breaking 336 this._addNewLine(); 337 return; 338 } 339 340 var textRenderer = fontNameOrFontDef instanceof cc.FontDefinition ? new cc.LabelTTF(text, fontNameOrFontDef) : new cc.LabelTTF(text, fontNameOrFontDef, fontSize); 341 var textRendererWidth = textRenderer.getContentSize().width; 342 this._leftSpaceWidth -= textRendererWidth; 343 if (this._leftSpaceWidth < 0) { 344 var overstepPercent = (-this._leftSpaceWidth) / textRendererWidth; 345 var curText = text; 346 var stringLength = curText.length; 347 var leftLength = stringLength * (1 - overstepPercent); 348 var leftWords = curText.substr(0, leftLength); 349 var cutWords = curText.substr(leftLength, curText.length - 1); 350 var validLeftLength = leftLength > 0; 351 352 if(this._lineBreakOnSpace){ 353 var lastSpaceIndex = leftWords.lastIndexOf(' '); 354 leftLength = lastSpaceIndex === -1 ? leftLength : lastSpaceIndex+1 ; 355 cutWords = curText.substr(leftLength, curText.length - 1); 356 validLeftLength = leftLength > 0 && cutWords !== " "; 357 } 358 359 if (validLeftLength) { 360 var leftRenderer = null; 361 if( fontNameOrFontDef instanceof cc.FontDefinition) 362 { 363 leftRenderer = new cc.LabelTTF(leftWords.substr(0, leftLength), fontNameOrFontDef); 364 leftRenderer.setOpacity(fontNameOrFontDef.fillStyle.a); //TODO: Verify that might not be needed... 365 }else{ 366 leftRenderer = new cc.LabelTTF(leftWords.substr(0, leftLength), fontNameOrFontDef, fontSize); 367 leftRenderer.setColor(color); 368 leftRenderer.setOpacity(color.a); 369 } 370 this._pushToContainer(leftRenderer); 371 } 372 373 this._addNewLine(); 374 this._handleTextRenderer(cutWords, fontNameOrFontDef, fontSize, color); 375 } else { 376 if( fontNameOrFontDef instanceof cc.FontDefinition) { 377 textRenderer.setOpacity(fontNameOrFontDef.fillStyle.a); //TODO: Verify that might not be needed... 378 }else { 379 textRenderer.setColor(color); 380 textRenderer.setOpacity(color.a); 381 } 382 this._pushToContainer(textRenderer); 383 } 384 }, 385 386 _handleImageRenderer: function (filePath, color, opacity) { 387 var imageRenderer = new cc.Sprite(filePath); 388 this._handleCustomRenderer(imageRenderer); 389 }, 390 391 _handleCustomRenderer: function (renderer) { 392 var imgSize = renderer.getContentSize(); 393 this._leftSpaceWidth -= imgSize.width; 394 if (this._leftSpaceWidth < 0) { 395 this._addNewLine(); 396 this._pushToContainer(renderer); 397 this._leftSpaceWidth -= imgSize.width; 398 } else 399 this._pushToContainer(renderer); 400 }, 401 402 _addNewLine: function () { 403 this._leftSpaceWidth = this._customSize.width; 404 this._elementRenders.push([]); 405 }, 406 407 /** 408 * Formats richText's renderer. 409 */ 410 formatRenderers: function () { 411 var newContentSizeHeight = 0, locRenderersContainer = this._elementRenderersContainer; 412 var locElementRenders = this._elementRenders; 413 var i, j, row, nextPosX, l; 414 var lineHeight, offsetX; 415 if (this._ignoreSize) { 416 var newContentSizeWidth = 0; 417 row = locElementRenders[0]; 418 nextPosX = 0; 419 420 for (j = 0; j < row.length; j++) { 421 l = row[j]; 422 l.setAnchorPoint(cc.p(0, 0)); 423 l.setPosition(nextPosX, 0); 424 locRenderersContainer.addChild(l, 1, j); 425 426 lineHeight = l.getLineHeight ? l.getLineHeight() : newContentSizeHeight; 427 428 var iSize = l.getContentSize(); 429 newContentSizeWidth += iSize.width; 430 newContentSizeHeight = Math.max(Math.min(newContentSizeHeight, lineHeight), iSize.height); 431 nextPosX += iSize.width; 432 } 433 434 //Text flow horizontal alignment: 435 if(this._textHorizontalAlignment !== cc.TEXT_ALIGNMENT_LEFT) { 436 offsetX = 0; 437 if (this._textHorizontalAlignment === cc.TEXT_ALIGNMENT_RIGHT) 438 offsetX = this._contentSize.width - nextPosX; 439 else if (this._textHorizontalAlignment === cc.TEXT_ALIGNMENT_CENTER) 440 offsetX = (this._contentSize.width - nextPosX) / 2; 441 442 for (j = 0; j < row.length; j++) 443 row[j].x += offsetX; 444 } 445 446 locRenderersContainer.setContentSize(newContentSizeWidth, newContentSizeHeight); 447 } else { 448 var maxHeights = []; 449 for (i = 0; i < locElementRenders.length; i++) { 450 row = locElementRenders[i]; 451 var maxHeight = 0; 452 for (j = 0; j < row.length; j++) { 453 l = row[j]; 454 lineHeight = l.getLineHeight ? l.getLineHeight() : l.getContentSize().height; 455 maxHeight = Math.max(Math.min(l.getContentSize().height, lineHeight), maxHeight); 456 } 457 maxHeights[i] = maxHeight; 458 newContentSizeHeight += maxHeights[i]; 459 } 460 461 var nextPosY = this._customSize.height; 462 463 for (i = 0; i < locElementRenders.length; i++) { 464 row = locElementRenders[i]; 465 nextPosX = 0; 466 nextPosY -= (maxHeights[i] + this._verticalSpace); 467 468 for (j = 0; j < row.length; j++) { 469 l = row[j]; 470 l.setAnchorPoint(cc.p(0, 0)); 471 l.setPosition(cc.p(nextPosX, nextPosY)); 472 locRenderersContainer.addChild(l, 1); 473 nextPosX += l.getContentSize().width; 474 } 475 //Text flow alignment(s) 476 if( this._textHorizontalAlignment !== cc.TEXT_ALIGNMENT_LEFT || this._textVerticalAlignment !== cc.VERTICAL_TEXT_ALIGNMENT_TOP) { 477 offsetX = 0; 478 if (this._textHorizontalAlignment === cc.TEXT_ALIGNMENT_RIGHT) 479 offsetX = this._contentSize.width - nextPosX; 480 else if (this._textHorizontalAlignment === cc.TEXT_ALIGNMENT_CENTER) 481 offsetX = (this._contentSize.width - nextPosX) / 2; 482 483 var offsetY = 0; 484 if (this._textVerticalAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM) 485 offsetY = this._customSize.height - newContentSizeHeight; 486 else if (this._textVerticalAlignment === cc.VERTICAL_TEXT_ALIGNMENT_CENTER) 487 offsetY = (this._customSize.height - newContentSizeHeight) / 2; 488 489 for (j = 0; j < row.length; j++) { 490 l = row[j]; 491 l.x += offsetX; 492 l.y -= offsetY; 493 } 494 } 495 } 496 497 locRenderersContainer.setContentSize(this._contentSize); 498 } 499 500 var length = locElementRenders.length; 501 for (i = 0; i<length; i++){ 502 locElementRenders[i].length = 0; 503 } 504 this._elementRenders.length = 0; 505 506 this.setContentSize(this._ignoreSize?this.getVirtualRendererSize():this._customSize); 507 this._updateContentSizeWithTextureSize(this._contentSize); 508 509 locRenderersContainer.setPosition(this._contentSize.width * 0.5, this._contentSize.height * 0.5); 510 }, 511 512 _pushToContainer: function (renderer) { 513 if (this._elementRenders.length <= 0) 514 return; 515 this._elementRenders[this._elementRenders.length - 1].push(renderer); 516 }, 517 518 _adaptRenderers: function(){ 519 this.formatText(); 520 }, 521 522 /** 523 * Sets vertical space 524 * @param {Number} space 525 */ 526 setVerticalSpace: function (space) { 527 this._verticalSpace = space; 528 }, 529 530 /** 531 * Sets anchor point 532 * @override 533 * @param {cc.Point} pt 534 */ 535 setAnchorPoint: function (pt) { 536 ccui.Widget.prototype.setAnchorPoint.call(this, pt); 537 this._elementRenderersContainer.setAnchorPoint(pt); 538 }, 539 _setAnchorX: function (x) { 540 ccui.Widget.prototype._setAnchorX.call(this, x); 541 this._elementRenderersContainer._setAnchorX(x); 542 }, 543 _setAnchorY: function (y) { 544 ccui.Widget.prototype._setAnchorY.call(this, y); 545 this._elementRenderersContainer._setAnchorY(y); 546 }, 547 548 /** 549 * Returns the renderer container's content size. 550 * @override 551 * @returns {cc.Size} 552 */ 553 getVirtualRendererSize: function(){ 554 return this._elementRenderersContainer.getContentSize(); 555 }, 556 557 /** 558 * Ignore the richText's custom size, If ignore is true that richText will ignore it's custom size, use renderer's content size, false otherwise. 559 * @param {Boolean} ignore 560 * @override 561 */ 562 ignoreContentAdaptWithSize: function (ignore) { 563 if (this._ignoreSize !== ignore) { 564 this._formatTextDirty = true; 565 ccui.Widget.prototype.ignoreContentAdaptWithSize.call(this, ignore); 566 } 567 }, 568 569 /** 570 * Gets the content size of ccui.RichText 571 * @override 572 * @return {cc.Size} 573 */ 574 getContentSize: function(){ 575 this.formatText(); 576 return cc.Node.prototype.getContentSize.call(this); 577 }, 578 _getWidth: function() { 579 this.formatText(); 580 return cc.Node.prototype._getWidth.call(this); 581 }, 582 _getHeight: function() { 583 this.formatText(); 584 return cc.Node.prototype._getHeight.call(this); 585 }, 586 587 setContentSize: function(contentSize, height){ 588 var locWidth = (height === undefined) ? contentSize.width : contentSize; 589 var locHeight = (height === undefined) ? contentSize.height : height; 590 ccui.Widget.prototype.setContentSize.call(this, locWidth, locHeight); 591 this._formatTextDirty = true; 592 }, 593 594 /** 595 * Returns the class name of ccui.RichText. 596 * @returns {string} 597 */ 598 getDescription: function(){ 599 return "RichText"; 600 }, 601 /** 602 * Allow child renderer to be affected by ccui.RichText's opacity 603 * @param {boolean} value 604 */ 605 setCascadeOpacityEnabled: function(value) { 606 this._super(value); 607 this._elementRenderersContainer.setCascadeOpacityEnabled(value); 608 }, 609 /** 610 * This allow the RichText layout to break line on space only like in Latin text format 611 * by default the property is false, which break the line on characters 612 * @param value 613 */ 614 setLineBreakOnSpace: function(value){ 615 this._lineBreakOnSpace = value; 616 this._formatTextDirty = true; 617 this.formatText(); 618 }, 619 /** 620 * Set the renderer horizontal flow alignment for the Control 621 * although it is named TextHorizontalAlignment, it should work with all type of renderer too. 622 * NOTE: we should rename this to setHorizontalAlignment directly 623 * 624 * @example 625 * var richText = new ccui.RichText(); 626 * richText.setTextHorizontalAlignment(cc.Text_ALIGNMENT_RIGHT); 627 * 628 * @param {Number} value - example cc.TEXT_ALIGNMENT_RIGHT 629 */ 630 setTextHorizontalAlignment: function(value){ 631 if(value !== this._textHorizontalAlignment) { 632 this._textHorizontalAlignment = value; 633 this.formatText(); 634 } 635 }, 636 /** 637 * Set the renderer vertical flow alignment for the Control 638 * although it is named TextVerticalAlignment, it should work with all type of renderer too. 639 * 640 * @example 641 * var richText = new ccui.RichText(); 642 * richText.setTextVerticalAlignment(cc.VERTICAL_TEXT_ALIGNMENT_CENTER); 643 * 644 * @param {Number} value - example cc.VERTICAL_TEXT_ALIGNMENT_CENTER 645 */ 646 setTextVerticalAlignment: function(value){ 647 if(value !== this._textVerticalAlignment) { 648 this._textVerticalAlignment = value; 649 this.formatText(); 650 } 651 } 652 }); 653 654 /** 655 * create a rich text 656 * @deprecated since v3.0, please use new ccui.RichText() instead. 657 * @returns {RichText} 658 */ 659 ccui.RichText.create = function(){ 660 return new ccui.RichText(); 661 }; 662 663 // Constants 664 //Rich element type 665 /** 666 * The text type of rich element. 667 * @constant 668 * @type {number} 669 */ 670 ccui.RichElement.TEXT = 0; 671 /** 672 * The image type of rich element. 673 * @constant 674 * @type {number} 675 */ 676 ccui.RichElement.IMAGE = 1; 677 /** 678 * The custom type of rich element. 679 * @constant 680 * @type {number} 681 */ 682 ccui.RichElement.CUSTOM = 2;