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