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 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 /** 28 * Text field delegate 29 * @class 30 * @extends cc.Class 31 */ 32 cc.TextFieldDelegate = cc.Class.extend(/** @lends cc.TextFieldDelegate# */{ 33 /** 34 * If the sender doesn't want to attach with IME, return true; 35 * @param {cc.TextFieldTTF} sender 36 * @return {Boolean} 37 */ 38 onTextFieldAttachWithIME:function (sender) { 39 return false; 40 }, 41 42 /** 43 * If the sender doesn't want to detach with IME, return true; 44 * @param {cc.TextFieldTTF} sender 45 * @return {Boolean} 46 */ 47 onTextFieldDetachWithIME:function (sender) { 48 return false; 49 }, 50 51 /** 52 * If the sender doesn't want to insert the text, return true; 53 * @param {cc.TextFieldTTF} sender 54 * @param {String} text 55 * @param {Number} len 56 * @return {Boolean} 57 */ 58 onTextFieldInsertText:function (sender, text, len) { 59 return false 60 }, 61 62 /** 63 * If the sender doesn't want to delete the delText, return true; 64 * @param {cc.TextFieldTTF} sender 65 * @param {String} delText 66 * @param {Number} len 67 * @return {Boolean} 68 */ 69 onTextFieldDeleteBackward:function (sender, delText, len) { 70 return false; 71 }, 72 73 /** 74 * If doesn't want draw sender as default, return true. 75 * @param {cc.TextFieldTTF} sender 76 * @return {Boolean} 77 */ 78 onDraw:function (sender) { 79 return false; 80 } 81 }); 82 83 /** 84 * A simple text input field with TTF font. 85 * @class 86 * @extends cc.LabelTTF 87 * 88 * @property {cc.Node} delegate - Delegate 89 * @property {Number} charCount - <@readonly> Characators count 90 * @property {String} placeHolder - Place holder for the field 91 * @property {cc.Color} colorSpaceHolder 92 * 93 * @param {String} placeholder 94 * @param {cc.Size} dimensions 95 * @param {Number} alignment 96 * @param {String} fontName 97 * @param {Number} fontSize 98 * 99 * @example 100 * //example 101 * // When five parameters 102 * var textField = new cc.TextFieldTTF("<click here for input>", cc.size(100,50), cc.TEXT_ALIGNMENT_LEFT,"Arial", 32); 103 * // When three parameters 104 * var textField = new cc.TextFieldTTF("<click here for input>", "Arial", 32); 105 */ 106 cc.TextFieldTTF = cc.LabelTTF.extend(/** @lends cc.TextFieldTTF# */{ 107 delegate:null, 108 colorSpaceHolder:null, 109 110 _colorText: null, 111 _lens:null, 112 _inputText:"", 113 _placeHolder:"", 114 _charCount:0, 115 _className:"TextFieldTTF", 116 117 /** 118 * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function. <br /> 119 * creates a cc.TextFieldTTF from a fontName, alignment, dimension and font size. 120 * @param {String} placeholder 121 * @param {cc.Size} dimensions 122 * @param {Number} alignment 123 * @param {String} fontName 124 * @param {Number} fontSize 125 */ 126 ctor:function (placeholder, dimensions, alignment, fontName, fontSize) { 127 this.colorSpaceHolder = cc.color(127, 127, 127); 128 this._colorText = cc.color(255,255,255, 255); 129 cc.imeDispatcher.addDelegate(this); 130 cc.LabelTTF.prototype.ctor.call(this); 131 132 if(fontSize !== undefined){ 133 this.initWithPlaceHolder("", dimensions, alignment, fontName, fontSize); 134 if(placeholder) 135 this.setPlaceHolder(placeholder); 136 }else if(fontName === undefined && alignment !== undefined){ 137 this.initWithString("", arguments[1], arguments[2]); 138 if(placeholder) 139 this.setPlaceHolder(placeholder); 140 } 141 }, 142 143 /** 144 * Gets the delegate. 145 * @return {cc.Node} 146 */ 147 getDelegate:function () { 148 return this.delegate; 149 }, 150 151 /** 152 * Set the delegate. 153 * @param {cc.Node} value 154 */ 155 setDelegate:function (value) { 156 this.delegate = value; 157 }, 158 159 /** 160 * Gets the char count. 161 * @return {Number} 162 */ 163 getCharCount:function () { 164 return this._charCount; 165 }, 166 167 /** 168 * Returns the color of space holder. 169 * @return {cc.Color} 170 */ 171 getColorSpaceHolder:function () { 172 return cc.color(this.colorSpaceHolder); 173 }, 174 175 /** 176 * Sets the color of space holder. 177 * @param {cc.Color} value 178 */ 179 setColorSpaceHolder:function (value) { 180 this.colorSpaceHolder.r = value.r; 181 this.colorSpaceHolder.g = value.g; 182 this.colorSpaceHolder.b = value.b; 183 this.colorSpaceHolder.a = cc.isUndefined(value.a) ? 255 : value.a; 184 }, 185 186 /** 187 * Sets the color of cc.TextFieldTTF's text. 188 * @param {cc.Color} textColor 189 */ 190 setTextColor:function(textColor){ 191 this._colorText.r = textColor.r; 192 this._colorText.g = textColor.g; 193 this._colorText.b = textColor.b; 194 this._colorText.a = cc.isUndefined(textColor.a) ? 255 : textColor.a; 195 }, 196 197 /** 198 * Initializes the cc.TextFieldTTF with a font name, alignment, dimension and font size 199 * @param {String} placeholder 200 * @param {cc.Size} dimensions 201 * @param {Number} alignment 202 * @param {String} fontName 203 * @param {Number} fontSize 204 * @return {Boolean} 205 * @example 206 * //example 207 * var textField = new cc.TextFieldTTF(); 208 * // When five parameters 209 * textField.initWithPlaceHolder("<click here for input>", cc.size(100,50), cc.TEXT_ALIGNMENT_LEFT,"Arial", 32); 210 * // When three parameters 211 * textField.initWithPlaceHolder("<click here for input>", "Arial", 32); 212 */ 213 initWithPlaceHolder:function (placeholder, dimensions, alignment, fontName, fontSize) { 214 switch (arguments.length) { 215 case 5: 216 if (placeholder) 217 this.setPlaceHolder(placeholder); 218 return this.initWithString(this._placeHolder,fontName, fontSize, dimensions, alignment); 219 break; 220 case 3: 221 if (placeholder) 222 this.setPlaceHolder(placeholder); 223 return this.initWithString(this._placeHolder, arguments[1], arguments[2]); 224 break; 225 default: 226 throw "Argument must be non-nil "; 227 break; 228 } 229 }, 230 231 /** 232 * Input text property 233 * @param {String} text 234 */ 235 setString:function (text) { 236 text = String(text); 237 this._inputText = text || ""; 238 239 // if there is no input text, display placeholder instead 240 if (!this._inputText.length){ 241 cc.LabelTTF.prototype.setString.call(this, this._placeHolder); 242 this.setColor(this.colorSpaceHolder); 243 } else { 244 cc.LabelTTF.prototype.setString.call(this,this._inputText); 245 this.setColor(this._colorText); 246 } 247 if(cc._renderType === cc._RENDER_TYPE_CANVAS) 248 this._updateTexture(); 249 this._charCount = this._inputText.length; 250 }, 251 252 /** 253 * Gets the string 254 * @return {String} 255 */ 256 getString:function () { 257 return this._inputText; 258 }, 259 260 /** 261 * Set the place holder. <br /> 262 * display this string if string equal "". 263 * @param {String} text 264 */ 265 setPlaceHolder:function (text) { 266 this._placeHolder = text || ""; 267 if (!this._inputText.length) { 268 cc.LabelTTF.prototype.setString.call(this,this._placeHolder); 269 this.setColor(this.colorSpaceHolder); 270 } 271 }, 272 273 /** 274 * Gets the place holder. <br /> 275 * default display string. 276 * @return {String} 277 */ 278 getPlaceHolder:function () { 279 return this._placeHolder; 280 }, 281 282 /** 283 * Render function using the canvas 2d context or WebGL context, internal usage only, please do not call this function. 284 * @param {CanvasRenderingContext2D | WebGLRenderingContext} ctx The render context 285 */ 286 draw:function (ctx) { 287 //console.log("size",this._contentSize); 288 var context = ctx || cc._renderContext; 289 if (this.delegate && this.delegate.onDraw(this)) 290 return; 291 292 cc.LabelTTF.prototype.draw.call(this, context); 293 }, 294 295 /** 296 * Recursive method that visit its children and draw them. 297 * @param {CanvasRenderingContext2D|WebGLRenderingContext} ctx 298 */ 299 visit: function(ctx){ 300 this._super(ctx); 301 }, 302 303 ////////////////////////////////////////////////////////////////////////// 304 // CCIMEDelegate interface 305 ////////////////////////////////////////////////////////////////////////// 306 /** 307 * Open keyboard and receive input text. 308 * @return {Boolean} 309 */ 310 attachWithIME:function () { 311 return cc.imeDispatcher.attachDelegateWithIME(this); 312 }, 313 314 /** 315 * End text input and close keyboard. 316 * @return {Boolean} 317 */ 318 detachWithIME:function () { 319 return cc.imeDispatcher.detachDelegateWithIME(this); 320 }, 321 322 /** 323 * Return whether to allow attach with IME. 324 * @return {Boolean} 325 */ 326 canAttachWithIME:function () { 327 return (this.delegate) ? (!this.delegate.onTextFieldAttachWithIME(this)) : true; 328 }, 329 330 /** 331 * When the delegate detach with IME, this method call by CCIMEDispatcher. 332 */ 333 didAttachWithIME:function () { 334 }, 335 336 /** 337 * Return whether to allow detach with IME. 338 * @return {Boolean} 339 */ 340 canDetachWithIME:function () { 341 return (this.delegate) ? (!this.delegate.onTextFieldDetachWithIME(this)) : true; 342 }, 343 344 /** 345 * When the delegate detach with IME, this method call by CCIMEDispatcher. 346 */ 347 didDetachWithIME:function () { 348 }, 349 350 /** 351 * Delete backward 352 */ 353 deleteBackward:function () { 354 var strLen = this._inputText.length; 355 if (strLen == 0) 356 return; 357 358 // get the delete byte number 359 var deleteLen = 1; // default, erase 1 byte 360 361 if (this.delegate && this.delegate.onTextFieldDeleteBackward(this, this._inputText[strLen - deleteLen], deleteLen)) { 362 // delegate don't want delete backward 363 return; 364 } 365 366 // if delete all text, show space holder string 367 if (strLen <= deleteLen) { 368 this._inputText = ""; 369 this._charCount = 0; 370 cc.LabelTTF.prototype.setString.call(this,this._placeHolder); 371 this.setColor(this.colorSpaceHolder); 372 return; 373 } 374 375 // set new input text 376 this.string = this._inputText.substring(0, strLen - deleteLen); 377 }, 378 379 /** 380 * Remove delegate 381 */ 382 removeDelegate:function () { 383 cc.imeDispatcher.removeDelegate(this); 384 }, 385 386 /** 387 * Append the text. <br /> 388 * Input the character. 389 * @param {String} text 390 * @param {Number} len 391 */ 392 insertText:function (text, len) { 393 var sInsert = text; 394 395 // insert \n means input end 396 var pos = sInsert.indexOf('\n'); 397 if (pos > -1) { 398 sInsert = sInsert.substring(0, pos); 399 } 400 401 if (sInsert.length > 0) { 402 if (this.delegate && this.delegate.onTextFieldInsertText(this, sInsert, sInsert.length)) { 403 // delegate doesn't want insert text 404 return; 405 } 406 407 var sText = this._inputText + sInsert; 408 this._charCount = sText.length; 409 this.string = sText; 410 } 411 412 if (pos == -1) 413 return; 414 415 // '\n' has inserted, let delegate process first 416 if (this.delegate && this.delegate.onTextFieldInsertText(this, "\n", 1)) 417 return; 418 419 // if delegate hasn't process, detach with ime as default 420 this.detachWithIME(); 421 }, 422 423 /** 424 * Gets the input text. 425 * @return {String} 426 */ 427 getContentText:function () { 428 return this._inputText; 429 }, 430 431 ////////////////////////////////////////////////////////////////////////// 432 // keyboard show/hide notification 433 ////////////////////////////////////////////////////////////////////////// 434 keyboardWillShow:function (info) { 435 }, 436 keyboardDidShow:function (info) { 437 }, 438 keyboardWillHide:function (info) { 439 }, 440 keyboardDidHide:function (info) { 441 } 442 }); 443 444 var _p = cc.TextFieldTTF.prototype; 445 446 // Extended properties 447 /** @expose */ 448 _p.charCount; 449 cc.defineGetterSetter(_p, "charCount", _p.getCharCount); 450 /** @expose */ 451 _p.placeHolder; 452 cc.defineGetterSetter(_p, "placeHolder", _p.getPlaceHolder, _p.setPlaceHolder); 453 454 455 /** 456 * Please use new TextFieldTTF instead. <br /> 457 * Creates a cc.TextFieldTTF from a fontName, alignment, dimension and font size. 458 * @deprecated since v3.0 Please use new TextFieldTTF instead. 459 * @param {String} placeholder 460 * @param {cc.Size} dimensions 461 * @param {Number} alignment 462 * @param {String} fontName 463 * @param {Number} fontSize 464 * @return {cc.TextFieldTTF|Null} 465 * @example 466 * //example 467 * // When five parameters 468 * var textField = cc.TextFieldTTF.create("<click here for input>", cc.size(100,50), cc.TEXT_ALIGNMENT_LEFT,"Arial", 32); 469 * // When three parameters 470 * var textField = cc.TextFieldTTF.create("<click here for input>", "Arial", 32); 471 */ 472 cc.TextFieldTTF.create = function (placeholder, dimensions, alignment, fontName, fontSize) { 473 return new cc.TextFieldTTF(placeholder, dimensions, alignment, fontName, fontSize); 474 }; 475 476