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 * Base class for ccui.UICCTextField 28 * @class 29 * @extends cc.TextFieldTTF 30 * 31 * @property {Boolean} maxLengthEnabled - Indicate whether max length limit is enabled 32 * @property {Number} maxLength - The max length of the text field 33 * @property {Boolean} passwordEnabled - Indicate whether the text field is for entering password 34 */ 35 ccui.UICCTextField = cc.TextFieldTTF.extend(/** @lends ccui.UICCTextField# */{ 36 maxLengthEnabled: false, 37 maxLength: 0, 38 passwordEnabled: false, 39 _passwordStyleText: "", 40 _attachWithIME: false, 41 _detachWithIME: false, 42 _insertText: false, 43 _deleteBackward: false, 44 _className: "UICCTextField", 45 ctor: function () { 46 cc.TextFieldTTF.prototype.ctor.call(this); 47 this.maxLengthEnabled = false; 48 this.maxLength = 0; 49 this.passwordEnabled = false; 50 this._passwordStyleText = "*"; 51 this._attachWithIME = false; 52 this._detachWithIME = false; 53 this._insertText = false; 54 this._deleteBackward = false; 55 }, 56 init: function () { 57 if (ccui.Widget.prototype.init.call(this)) { 58 this.setTouchEnabled(true); 59 return true; 60 } 61 return false; 62 }, 63 onEnter: function () { 64 cc.TextFieldTTF.prototype.onEnter.call(this); 65 cc.TextFieldTTF.prototype.setDelegate.call(this, this); 66 }, 67 68 //CCTextFieldDelegate 69 70 onTextFieldAttachWithIME: function (sender) { 71 this.setAttachWithIME(true); 72 return false; 73 }, 74 75 onTextFieldInsertText: function (sender, text, len) { 76 if (len == 1 && text == "\n") { 77 return false; 78 } 79 this.setInsertText(true); 80 if (this.maxLengthEnabled) { 81 if (cc.TextFieldTTF.prototype.getCharCount.call(this) >= this.maxLength) { 82 return true; 83 } 84 } 85 86 return false; 87 }, 88 89 onTextFieldDeleteBackward: function (sender, delText, nLen) { 90 this.setDeleteBackward(true); 91 return false; 92 }, 93 94 onTextFieldDetachWithIME: function (sender) { 95 this.setDetachWithIME(true); 96 return false; 97 }, 98 99 insertText: function (text, len) { 100 var str_text = text; 101 var locString = cc.TextFieldTTF.prototype.getString.call(this); 102 var str_len = locString.length; 103 var multiple, header; 104 if (text != "\n") { 105 if (this.maxLengthEnabled) { 106 multiple = 1; 107 header = text.charCodeAt(0); 108 if (header < 0 || header > 127) { 109 multiple = 3; 110 } 111 112 if (str_len + len > this.maxLength * multiple) { 113 str_text = str_text.substr(0, this.maxLength * multiple); 114 len = this.maxLength * multiple; 115 } 116 } 117 } 118 cc.TextFieldTTF.prototype.insertText.call(this, str_text, len); 119 120 // password 121 if (this.passwordEnabled) { 122 if (cc.TextFieldTTF.prototype.getCharCount.call(this) > 0) { 123 this.setPasswordText(this._inputText); 124 } 125 } 126 }, 127 128 deleteBackward: function () { 129 cc.TextFieldTTF.prototype.deleteBackward.call(this); 130 131 if (cc.TextFieldTTF.prototype.getCharCount.call(this) > 0) { 132 // password 133 if (this.passwordEnabled) { 134 this.setPasswordText(this._inputText); 135 } 136 } 137 }, 138 139 openIME: function () { 140 cc.TextFieldTTF.prototype.attachWithIME.call(this); 141 }, 142 143 closeIME: function () { 144 cc.TextFieldTTF.prototype.detachWithIME.call(this); 145 }, 146 onDraw: function (sender) { 147 return false; 148 }, 149 setMaxLengthEnabled: function (enable) { 150 this.maxLengthEnabled = enable; 151 }, 152 153 isMaxLengthEnabled: function () { 154 return this.maxLengthEnabled; 155 }, 156 157 setMaxLength: function (length) { 158 this.maxLength = length; 159 }, 160 161 getMaxLength: function () { 162 return this.maxLength; 163 }, 164 165 getCharCount: function () { 166 return cc.TextFieldTTF.prototype.getCharCount.call(this); 167 }, 168 169 setPasswordEnabled: function (enable) { 170 this.passwordEnabled = enable; 171 }, 172 173 isPasswordEnabled: function () { 174 return this.passwordEnabled; 175 }, 176 177 setPasswordStyleText: function (styleText) { 178 if (styleText.length > 1) { 179 return; 180 } 181 var header = styleText.charCodeAt(0); 182 if (header < 33 || header > 126) { 183 return; 184 } 185 this._passwordStyleText = styleText; 186 }, 187 188 setPasswordText: function (text) { 189 var tempStr = ""; 190 for (var i = 0; i < text.length; ++i) { 191 tempStr += this._passwordStyleText; 192 } 193 cc.LabelTTF.prototype.setString.call(this, tempStr); 194 }, 195 196 setAttachWithIME: function (attach) { 197 this._attachWithIME = attach; 198 }, 199 200 getAttachWithIME: function () { 201 return this._attachWithIME; 202 }, 203 204 setDetachWithIME: function (detach) { 205 this._detachWithIME = detach; 206 }, 207 208 getDetachWithIME: function () { 209 return this._detachWithIME; 210 }, 211 212 setInsertText: function (insert) { 213 this._insertText = insert; 214 }, 215 216 getInsertText: function () { 217 return this._insertText; 218 }, 219 220 setDeleteBackward: function (deleteBackward) { 221 this._deleteBackward = deleteBackward; 222 }, 223 224 getDeleteBackward: function () { 225 return this._deleteBackward; 226 } 227 }); 228 229 ccui.UICCTextField.create = function (placeholder, fontName, fontSize) { 230 var ret = new ccui.UICCTextField(); 231 if (ret && ret.initWithString("", fontName, fontSize)) { 232 if (placeholder) { 233 ret.setPlaceHolder(placeholder); 234 } 235 return ret; 236 } 237 return null; 238 }; 239 240 /** 241 * Base class for ccui.TextField 242 * @class 243 * @extends ccui.Widget 244 * 245 * @property {String} string - The content string of the label 246 * @property {Number} placeHolder - The place holder of the text field 247 * @property {String} font - The text field font with a style string: e.g. "18px Verdana" 248 * @property {String} fontName - The text field font name 249 * @property {Number} fontSize - The text field font size 250 * @property {Boolean} maxLengthEnabled - Indicate whether max length limit is enabled 251 * @property {Number} maxLength - The max length of the text field 252 * @property {Boolean} passwordEnabled - Indicate whether the text field is for entering password 253 */ 254 ccui.TextField = ccui.Widget.extend(/** @lends ccui.TextField# */{ 255 _textFieldRender: null, 256 _touchWidth: 0, 257 _touchHeight: 0, 258 _useTouchArea: false, 259 _textFieldEventListener: null, 260 _textFieldEventSelector: null, 261 _attachWithIMEListener: null, 262 _detachWithIMEListener: null, 263 _insertTextListener: null, 264 _deleteBackwardListener: null, 265 _attachWithIMESelector: null, 266 _detachWithIMESelector: null, 267 _insertTextSelector: null, 268 _deleteBackwardSelector: null, 269 _passwordStyleText: "", 270 271 /** 272 * allocates and initializes a UITextField. 273 * Constructor of ccui.TextField 274 * @example 275 * // example 276 * var uiTextField = new ccui.TextField(); 277 */ 278 ctor: function () { 279 ccui.Widget.prototype.ctor.call(this); 280 }, 281 282 onEnter: function () { 283 ccui.Widget.prototype.onEnter.call(this); 284 this.setUpdateEnabled(true); 285 }, 286 287 initRenderer: function () { 288 this._textFieldRender = ccui.UICCTextField.create("input words here", "Thonburi", 20); 289 cc.Node.prototype.addChild.call(this, this._textFieldRender, ccui.TextField.RENDERER_ZORDER, -1); 290 291 }, 292 293 /** 294 * Set touch size 295 * @param {cc.Size} size 296 */ 297 setTouchSize: function (size) { 298 this._useTouchArea = true; 299 this._touchWidth = size.width; 300 this._touchHeight = size.height; 301 }, 302 303 /** 304 * Get touch size. 305 * @returns {cc.Size} 306 */ 307 getTouchSize: function () { 308 return cc.size(this._touchWidth, this._touchHeight); 309 }, 310 311 /** 312 * Changes the string value of textField. 313 * @param {String} text 314 */ 315 setText: function (text) { 316 if (!text) { 317 return; 318 } 319 text = String(text); 320 if (this.isMaxLengthEnabled()) { 321 text = text.substr(0, this.getMaxLength()); 322 } 323 if (this.isPasswordEnabled()) { 324 this._textFieldRender.setPasswordText(text); 325 this._textFieldRender.insertText(text, text.length); 326 } 327 else { 328 this._textFieldRender.setString(text); 329 } 330 this._textFieldRender.setString(text); 331 this.textfieldRendererScaleChangedWithSize(); 332 }, 333 334 /** 335 * @param {String} value 336 */ 337 setPlaceHolder: function (value) { 338 this._textFieldRender.setPlaceHolder(value); 339 this.textfieldRendererScaleChangedWithSize(); 340 }, 341 342 /** 343 * @returns {String} 344 */ 345 getPlaceHolder: function () { 346 return this._textFieldRender.getPlaceHolder(); 347 }, 348 349 _setFont: function (font) { 350 this._textFieldRender._setFont(font); 351 this.textfieldRendererScaleChangedWithSize(); 352 }, 353 354 _getFont: function () { 355 return this._textFieldRender._getFont(); 356 }, 357 358 /** 359 * Set font size for text field content 360 * @param {cc.Size} size 361 */ 362 setFontSize: function (size) { 363 this._textFieldRender.setFontSize(size); 364 this.textfieldRendererScaleChangedWithSize(); 365 }, 366 367 /** 368 * Get font size for text field content 369 * @param {cc.Size} size 370 */ 371 getFontSize: function () { 372 return this._textFieldRender.getFontSize(); 373 }, 374 375 /** 376 * Set font name for text field content 377 * @param {String} name 378 */ 379 setFontName: function (name) { 380 this._textFieldRender.setFontName(name); 381 this.textfieldRendererScaleChangedWithSize(); 382 }, 383 384 /** 385 * Get font name for text field content 386 * @param {cc.Size} size 387 */ 388 getFontName: function () { 389 return this._textFieldRender.getFontName(); 390 }, 391 392 /** 393 * detach with IME 394 */ 395 didNotSelectSelf: function () { 396 this._textFieldRender.detachWithIME(); 397 }, 398 399 /** 400 * get textField string value 401 * @returns {String} 402 */ 403 getStringValue: function () { 404 return this._textFieldRender.getString(); 405 }, 406 407 /** 408 * touch began 409 * @param {cc.Point} touchPoint 410 */ 411 onTouchBegan: function (touchPoint) { 412 var pass = ccui.Widget.prototype.onTouchBegan.call(this, touchPoint); 413 return pass; 414 }, 415 416 /** 417 * touch ended 418 * @param touchPoint 419 */ 420 onTouchEnded: function (touchPoint) { 421 ccui.Widget.prototype.onTouchEnded.call(this, touchPoint); 422 this._textFieldRender.attachWithIME(); 423 }, 424 425 /** 426 * @param {Boolean} enable 427 */ 428 setMaxLengthEnabled: function (enable) { 429 this._textFieldRender.setMaxLengthEnabled(enable); 430 }, 431 432 /** 433 * @returns {Boolean} 434 */ 435 isMaxLengthEnabled: function () { 436 return this._textFieldRender.isMaxLengthEnabled(); 437 }, 438 439 /** 440 * @param {number} length 441 */ 442 setMaxLength: function (length) { 443 this._textFieldRender.setMaxLength(length); 444 }, 445 446 /** 447 * @returns {number} length 448 */ 449 getMaxLength: function () { 450 return this._textFieldRender.getMaxLength(); 451 }, 452 453 /** 454 * @param {Boolean} enable 455 */ 456 setPasswordEnabled: function (enable) { 457 this._textFieldRender.setPasswordEnabled(enable); 458 }, 459 460 /** 461 * @returns {Boolean} 462 */ 463 isPasswordEnabled: function () { 464 return this._textFieldRender.isPasswordEnabled(); 465 }, 466 467 /** 468 * @param {String} enable 469 */ 470 setPasswordStyleText: function (styleText) { 471 this._textFieldRender.setPasswordStyleText(styleText); 472 this._passwordStyleText = styleText; 473 }, 474 475 /** 476 * @returns {String} 477 */ 478 getPasswordStyleText: function () { 479 return this._passwordStyleText; 480 }, 481 482 update: function (dt) { 483 if (this.getAttachWithIME()) { 484 this.attachWithIMEEvent(); 485 this.setAttachWithIME(false); 486 } 487 if (this.getDetachWithIME()) { 488 this.detachWithIMEEvent(); 489 this.setDetachWithIME(false); 490 } 491 if (this.getInsertText()) { 492 this.insertTextEvent(); 493 this.setInsertText(false); 494 495 this.textfieldRendererScaleChangedWithSize(); 496 } 497 if (this.getDeleteBackward()) { 498 this.deleteBackwardEvent(); 499 this.setDeleteBackward(false); 500 } 501 }, 502 503 /** 504 * get whether attach with IME. 505 * @returns {Boolean} 506 */ 507 getAttachWithIME: function () { 508 return this._textFieldRender.getAttachWithIME(); 509 }, 510 511 /** 512 * set attach with IME. 513 * @param {Boolean} attach 514 */ 515 setAttachWithIME: function (attach) { 516 this._textFieldRender.setAttachWithIME(attach); 517 }, 518 519 /** 520 * get whether eetach with IME. 521 * @returns {Boolean} 522 */ 523 getDetachWithIME: function () { 524 return this._textFieldRender.getDetachWithIME(); 525 }, 526 527 /** 528 * set detach with IME. 529 * @param {Boolean} detach 530 */ 531 setDetachWithIME: function (detach) { 532 this._textFieldRender.setDetachWithIME(detach); 533 }, 534 535 /** 536 * get insertText 537 * @returns {String} 538 */ 539 getInsertText: function () { 540 return this._textFieldRender.getInsertText(); 541 }, 542 543 /** 544 * set insertText 545 * @param {String} insertText 546 */ 547 setInsertText: function (insertText) { 548 this._textFieldRender.setInsertText(insertText); 549 }, 550 551 /** 552 * @returns {Boolean} 553 */ 554 getDeleteBackward: function () { 555 return this._textFieldRender.getDeleteBackward(); 556 }, 557 558 /** 559 * @param {Boolean} deleteBackward 560 */ 561 setDeleteBackward: function (deleteBackward) { 562 this._textFieldRender.setDeleteBackward(deleteBackward); 563 }, 564 565 attachWithIMEEvent: function () { 566 if (this._textFieldEventListener && this._textFieldEventSelector) { 567 this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_ATTACH_WITH_ME); 568 } 569 }, 570 571 detachWithIMEEvent: function () { 572 if (this._textFieldEventListener && this._textFieldEventSelector) { 573 this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_DETACH_WITH_ME); 574 } 575 }, 576 577 insertTextEvent: function () { 578 if (this._textFieldEventListener && this._textFieldEventSelector) { 579 this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_INSERT_TEXT); 580 } 581 }, 582 583 deleteBackwardEvent: function () { 584 if (this._textFieldEventListener && this._textFieldEventSelector) { 585 this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_DELETE_BACKWARD); 586 } 587 }, 588 589 /** 590 * add event listener 591 * @param {Function} selector 592 * @param {Object} target 593 */ 594 addEventListenerTextField: function (selector, target) { 595 this._textFieldEventSelector = selector; 596 this._textFieldEventListener = target; 597 }, 598 599 /** 600 * check hit 601 * @param {cc.Point} pt 602 * @returns {boolean} 603 */ 604 hitTest: function (pt) { 605 var nsp = this.convertToNodeSpace(pt); 606 var locSize = this._textFieldRender.getContentSize(); 607 var bb = cc.rect(-locSize.width * this._anchorPoint.x, -locSize.height * this._anchorPoint.y, locSize.width, locSize.height); 608 if (nsp.x >= bb.x && nsp.x <= bb.x + bb.width && nsp.y >= bb.y && nsp.y <= bb.y + bb.height) { 609 return true; 610 } 611 return false; 612 }, 613 614 /** 615 * override "setAnchorPoint" of widget. 616 * @param {cc.Point|Number} point The anchor point of UILabelBMFont or The anchor point.x of UILabelBMFont. 617 * @param {Number} [y] The anchor point.y of UILabelBMFont. 618 */ 619 setAnchorPoint: function (point, y) { 620 if (y === undefined) { 621 ccui.Widget.prototype.setAnchorPoint.call(this, point); 622 this._textFieldRender.setAnchorPoint(point); 623 } else { 624 ccui.Widget.prototype.setAnchorPoint.call(this, point, y); 625 this._textFieldRender.setAnchorPoint(point, y); 626 } 627 }, 628 _setAnchorX: function (value) { 629 ccui.Widget.prototype._setAnchorX.call(this, value); 630 this._textFieldRender._setAnchorX(value); 631 }, 632 _setAnchorY: function (value) { 633 ccui.Widget.prototype._setAnchorY.call(this, value); 634 this._textFieldRender._setAnchorY(value); 635 }, 636 637 onSizeChanged: function () { 638 ccui.Widget.prototype.onSizeChanged.call(this); 639 this.textfieldRendererScaleChangedWithSize(); 640 }, 641 642 textfieldRendererScaleChangedWithSize: function () { 643 if (this._ignoreSize) { 644 this._textFieldRender.setScale(1.0); 645 var rendererSize = this.getContentSize(); 646 this._size.width = rendererSize.width; 647 this._size.height = rendererSize.height; 648 } 649 else { 650 var textureSize = this.getContentSize(); 651 if (textureSize.width <= 0.0 || textureSize.height <= 0.0) { 652 this._textFieldRender.setScale(1.0); 653 return; 654 } 655 var scaleX = this._size.width / textureSize.width; 656 var scaleY = this._size.height / textureSize.height; 657 this._textFieldRender.setScaleX(scaleX); 658 this._textFieldRender.setScaleY(scaleY); 659 } 660 }, 661 662 /** 663 * override "getContentSize" method of widget. 664 * @returns {cc.Size} 665 */ 666 getContentSize: function () { 667 return this._textFieldRender.getContentSize(); 668 }, 669 _getWidth: function () { 670 return this._textFieldRender._getWidth(); 671 }, 672 _getHeight: function () { 673 return this._textFieldRender._getHeight(); 674 }, 675 676 /** 677 * override "getContentSize" method of widget. 678 * @returns {cc.Node} 679 */ 680 getVirtualRenderer: function () { 681 return this._textFieldRender; 682 }, 683 684 updateTextureColor: function () { 685 this.updateColorToRenderer(this._textFieldRender); 686 }, 687 688 updateTextureOpacity: function () { 689 this.updateOpacityToRenderer(this._textFieldRender); 690 }, 691 692 /** 693 * Returns the "class name" of widget. 694 * @returns {string} 695 */ 696 getDescription: function () { 697 return "TextField"; 698 }, 699 700 attachWithIME: function () { 701 this._textFieldRender.attachWithIME(); 702 }, 703 704 createCloneInstance: function () { 705 return ccui.TextField.create(); 706 }, 707 708 copySpecialProperties: function (textField) { 709 this.setText(textField._textFieldRender.getString()); 710 this.setPlaceHolder(textField.getStringValue()); 711 this.setFontSize(textField._textFieldRender.getFontSize()); 712 this.setFontName(textField._textFieldRender.getFontName()); 713 this.setMaxLengthEnabled(textField.isMaxLengthEnabled()); 714 this.setMaxLength(textField.getMaxLength()); 715 this.setPasswordEnabled(textField.isPasswordEnabled()); 716 this.setPasswordStyleText(textField._passwordStyleText); 717 this.setAttachWithIME(textField.getAttachWithIME()); 718 this.setDetachWithIME(textField.getDetachWithIME()); 719 this.setInsertText(textField.getInsertText()); 720 this.setDeleteBackward(textField.getDeleteBackward()); 721 } 722 }); 723 724 var _p = ccui.TextField.prototype; 725 726 // Extended properties 727 /** @expose */ 728 _p.string; 729 cc.defineGetterSetter(_p, "string", _p.getStringValue, _p.setText); 730 /** @expose */ 731 _p.placeHolder; 732 cc.defineGetterSetter(_p, "placeHolder", _p.getPlaceHolder, _p.setPlaceHolder); 733 /** @expose */ 734 _p.font; 735 cc.defineGetterSetter(_p, "font", _p._getFont, _p._setFont); 736 /** @expose */ 737 _p.fontSize; 738 cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize); 739 /** @expose */ 740 _p.fontName; 741 cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName); 742 /** @expose */ 743 _p.maxLengthEnabled; 744 cc.defineGetterSetter(_p, "maxLengthEnabled", _p.isMaxLengthEnabled, _p.setMaxLengthEnabled); 745 /** @expose */ 746 _p.maxLength; 747 cc.defineGetterSetter(_p, "maxLength", _p.getMaxLength, _p.setMaxLength); 748 /** @expose */ 749 _p.passwordEnabled; 750 cc.defineGetterSetter(_p, "passwordEnabled", _p.isPasswordEnabled, _p.setPasswordEnabled); 751 752 _p = null; 753 754 /** 755 * allocates and initializes a UITextField. 756 * @constructs 757 * @return {ccui.TextField} 758 * @example 759 * // example 760 * var uiTextField = ccui.TextField.create(); 761 */ 762 ccui.TextField.create = function () { 763 return new ccui.TextField(); 764 }; 765 766 // Constants 767 //TextField event 768 ccui.TextField.EVENT_ATTACH_WITH_ME = 0; 769 ccui.TextField.EVENT_DETACH_WITH_ME = 1; 770 ccui.TextField.EVENT_INSERT_TEXT = 2; 771 ccui.TextField.EVENT_DELETE_BACKWARD = 3; 772 773 ccui.TextField.RENDERER_ZORDER = -1;