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