1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga 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 * f 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 cc.TextFieldTTF = cc.LabelTTF.extend(/** @lends cc.TextFieldTTF# */{ 89 _lens:null, 90 _inputText:"", 91 _placeHolder:"", 92 _charCount:0, 93 _delegate:null, 94 _ColorSpaceHolder:null, 95 /** 96 * Constructor 97 */ 98 ctor:function () { 99 this._ColorSpaceHolder = new cc.Color3B(127, 127, 127); 100 cc.IMEDispatcher.getInstance().addDelegate(this); 101 this._super(); 102 }, 103 104 /** 105 * @return {cc.Node} 106 */ 107 getDelegate:function () { 108 return this._delegate; 109 }, 110 111 /** 112 * @param {cc.Node} value 113 */ 114 setDelegate:function (value) { 115 this._delegate = value; 116 }, 117 118 /** 119 * @return {Number} 120 */ 121 getCharCount:function () { 122 return this._charCount; 123 }, 124 125 /** 126 * @return {cc.Color3B} 127 */ 128 getColorSpaceHolder:function () { 129 return this._ColorSpaceHolder; 130 }, 131 132 /** 133 * @param {cc.Color3B} value 134 */ 135 setColorSpaceHolder:function (value) { 136 this._ColorSpaceHolder = value; 137 }, 138 /** 139 * Initializes the cc.TextFieldTTF with a font name, alignment, dimension and font size 140 * @param {String} placeholder 141 * @param {cc.Size} dimensions 142 * @param {Number} alignment 143 * @param {String} fontName 144 * @param {Number} fontSize 145 * @return {Boolean} 146 * @example 147 * //example 148 * var textField = new cc.TextFieldTTF(); 149 * // When five parameters 150 * textField.initWithPlaceHolder("<click here for input>", cc.size(100,50), cc.TEXT_ALIGNMENT_LEFT,"Arial", 32); 151 * // When three parameters 152 * textField.initWithPlaceHolder("<click here for input>", "Arial", 32); 153 */ 154 initWithPlaceHolder:function (placeholder, dimensions, alignment, fontName, fontSize) { 155 switch (arguments.length) { 156 case 5: 157 if (placeholder) { 158 this._placeHolder = placeholder; 159 } 160 return this.initWithString(this._placeHolder, dimensions, alignment, fontName, fontSize); 161 break; 162 case 3: 163 if (placeholder) { 164 this._placeHolder = placeholder; 165 } 166 fontName = arguments[1]; 167 fontSize = arguments[2]; 168 return this.initWithString(this._placeHolder, fontName, fontSize); 169 break; 170 default: 171 throw "Argument must be non-nil "; 172 break; 173 } 174 }, 175 176 /** 177 * Input text property 178 * @param {String} text 179 * @param {Boolean} isCallParent 180 */ 181 setString:function (text, isCallParent) { 182 if (isCallParent && isCallParent == true) { 183 this._super(text); 184 return; 185 } 186 187 this._inputText = text || ""; 188 189 // if there is no input text, display placeholder instead 190 if (!this._inputText.length) 191 this._super(this._placeHolder); 192 else 193 this._super(this._inputText); 194 this._charCount = this._inputText.length; 195 }, 196 197 /** 198 * @return {String} 199 */ 200 getString:function () { 201 return this._inputText; 202 }, 203 204 /** 205 * @param {String} text 206 */ 207 setPlaceHolder:function (text) { 208 this._placeHolder = text || ""; 209 if (!this._inputText.length) { 210 this.setString(this._placeHolder, true); 211 } 212 }, 213 214 /** 215 * @return {String} 216 */ 217 getPlaceHolder:function () { 218 return this._placeHolder; 219 }, 220 221 /** 222 * @param {CanvasContext} ctx 223 */ 224 draw:function (ctx) { 225 var context = ctx || cc.renderContext; 226 if (this._delegate && this._delegate.onDraw(this)) 227 return; 228 229 if (this._inputText && this._inputText.length > 0) { 230 this._super(context); 231 return; 232 } 233 234 // draw placeholder 235 var color = this.getColor(); 236 this.setColor(this._ColorSpaceHolder); 237 this._super(context); 238 this.setColor(color); 239 }, 240 241 ////////////////////////////////////////////////////////////////////////// 242 // CCIMEDelegate interface 243 ////////////////////////////////////////////////////////////////////////// 244 /** 245 * Open keyboard and receive input text. 246 * @return {Boolean} 247 */ 248 attachWithIME:function () { 249 return cc.IMEDispatcher.getInstance().attachDelegateWithIME(this); 250 }, 251 252 /** 253 * End text input and close keyboard. 254 * @return {Boolean} 255 */ 256 detachWithIME:function () { 257 return cc.IMEDispatcher.getInstance().detachDelegateWithIME(this); 258 }, 259 260 /** 261 * @return {Boolean} 262 */ 263 canAttachWithIME:function () { 264 return (this._delegate) ? (!this._delegate.onTextFieldAttachWithIME(this)) : true; 265 }, 266 267 /** 268 * When the delegate detach with IME, this method call by CCIMEDispatcher. 269 */ 270 didAttachWithIME:function () { 271 }, 272 273 /** 274 * @return {Boolean} 275 */ 276 canDetachWithIME:function () { 277 return (this._delegate) ? (!this._delegate.onTextFieldDetachWithIME(this)) : true; 278 }, 279 280 /** 281 * When the delegate detach with IME, this method call by CCIMEDispatcher. 282 */ 283 didDetachWithIME:function () { 284 }, 285 286 /** 287 * Delete backward 288 */ 289 deleteBackward:function () { 290 var strLen = this._inputText.length; 291 if (strLen == 0) 292 return; 293 294 // get the delete byte number 295 var deleteLen = 1; // default, erase 1 byte 296 297 if (this._delegate && this._delegate.onTextFieldDeleteBackward(this, this._inputText[strLen - deleteLen], deleteLen)) { 298 // delegate don't want delete backward 299 return; 300 } 301 302 // if delete all text, show space holder string 303 if (strLen <= deleteLen) { 304 this._inputText = ""; 305 this._charCount = 0; 306 this.setString(this._placeHolder, true); 307 return; 308 } 309 310 // set new input text 311 var sText = this._inputText.substring(0, strLen - deleteLen); 312 this.setString(sText, false); 313 }, 314 315 /** 316 * Remove delegate 317 */ 318 removeDelegate:function () { 319 cc.IMEDispatcher.getInstance().removeDelegate(this); 320 }, 321 322 /** 323 * @param {String} text 324 * @param {Number} len 325 */ 326 insertText:function (text, len) { 327 var sInsert = text; 328 329 // insert \n means input end 330 var pos = sInsert.indexOf('\n'); 331 if (pos > -1) { 332 sInsert = sInsert.substring(0, pos); 333 } 334 335 if (sInsert.length > 0) { 336 if (this._delegate && this._delegate.onTextFieldInsertText(this, sInsert, sInsert.length)) { 337 // delegate doesn't want insert text 338 return; 339 } 340 341 var sText = this._inputText + sInsert; 342 this._charCount = sText.length; 343 this.setString(sText); 344 } 345 346 if (pos == -1) 347 return; 348 349 // '\n' has inserted, let delegate process first 350 if (this._delegate && this._delegate.onTextFieldInsertText(this, "\n", 1)) 351 return; 352 353 // if delegate hasn't process, detach with ime as default 354 this.detachWithIME(); 355 }, 356 /** 357 * @return {String} 358 */ 359 getContentText:function () { 360 return this._inputText; 361 }, 362 363 ////////////////////////////////////////////////////////////////////////// 364 // keyboard show/hide notification 365 ////////////////////////////////////////////////////////////////////////// 366 keyboardWillShow:function (info) { 367 }, 368 keyboardDidShow:function (info) { 369 }, 370 keyboardWillHide:function (info) { 371 }, 372 keyboardDidHide:function (info) { 373 } 374 }); 375 376 /** 377 * creates a cc.TextFieldTTF from a fontName, alignment, dimension and font size 378 * @param {String} placeholder 379 * @param {cc.Size} dimensions 380 * @param {Number} alignment 381 * @param {String} fontName 382 * @param {Number} fontSize 383 * @return {cc.TextFieldTTF|Null} 384 * @example 385 * //example 386 * // When five parameters 387 * var textField = cc.TextFieldTTF.create("<click here for input>", cc.size(100,50), cc.TEXT_ALIGNMENT_LEFT,"Arial", 32); 388 * // When three parameters 389 * var textField = cc.TextFieldTTF.create("<click here for input>", "Arial", 32); 390 */ 391 cc.TextFieldTTF.create = function (placeholder, dimensions, alignment, fontName, fontSize) { 392 var ret; 393 switch (arguments.length) { 394 case 5: 395 ret = new cc.TextFieldTTF(); 396 if (ret && ret.initWithPlaceHolder("", dimensions, alignment, fontName, fontSize)) { 397 if (placeholder) 398 ret.setPlaceHolder(placeholder); 399 return ret; 400 } 401 return null; 402 break; 403 case 3: 404 ret = new cc.TextFieldTTF(); 405 fontName = arguments[1]; 406 fontSize = arguments[2]; 407 if (ret && ret.initWithString(["", fontName, fontSize])) { 408 if (placeholder) 409 ret.setPlaceHolder(placeholder); 410 return ret; 411 } 412 return null; 413 break; 414 default: 415 throw "Argument must be non-nil "; 416 break; 417 } 418 }; 419 420