1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2012 James Chen
  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  * @constant
 28  * @type Number
 29  */
 30 cc.KEYBOARD_RETURNTYPE_DEFAULT = 0;
 31 
 32 /**
 33  * @constant
 34  * @type Number
 35  */
 36 cc.KEYBOARD_RETURNTYPE_DONE = 1;
 37 
 38 /**
 39  * @constant
 40  * @type Number
 41  */
 42 cc.KEYBOARD_RETURNTYPE_SEND = 2;
 43 
 44 /**
 45  * @constant
 46  * @type Number
 47  */
 48 cc.KEYBOARD_RETURNTYPE_SEARCH = 3;
 49 
 50 /**
 51  * @constant
 52  * @type Number
 53  */
 54 cc.KEYBOARD_RETURNTYPE_GO = 4;
 55 
 56 /**
 57  * The EditBoxInputMode defines the type of text that the user is allowed * to enter.
 58  * @constant
 59  * @type Number
 60  */
 61 cc.EDITBOX_INPUT_MODE_ANY = 0;
 62 
 63 /**
 64  * The user is allowed to enter an e-mail address.
 65  * @constant
 66  * @type Number
 67  */
 68 cc.EDITBOX_INPUT_MODE_EMAILADDR = 1;
 69 
 70 /**
 71  * The user is allowed to enter an integer value.
 72  * @constant
 73  * @type Number
 74  */
 75 cc.EDITBOX_INPUT_MODE_NUMERIC = 2;
 76 
 77 /**
 78  * The user is allowed to enter a phone number.
 79  * @constant
 80  * @type Number
 81  */
 82 cc.EDITBOX_INPUT_MODE_PHONENUMBER = 3;
 83 
 84 /**
 85  * The user is allowed to enter a URL.
 86  * @constant
 87  * @type Number
 88  */
 89 cc.EDITBOX_INPUT_MODE_URL = 4;
 90 
 91 /**
 92  * The user is allowed to enter a real number value.
 93  * This extends kEditBoxInputModeNumeric by allowing a decimal point.
 94  * @constant
 95  * @type Number
 96  */
 97 cc.EDITBOX_INPUT_MODE_DECIMAL = 5;
 98 
 99 /**
100  * The user is allowed to enter any text, except for line breaks.
101  * @constant
102  * @type Number
103  */
104 cc.EDITBOX_INPUT_MODE_SINGLELINE = 6;
105 
106 /**
107  * Indicates that the text entered is confidential data that should be
108  * obscured whenever possible. This implies EDIT_BOX_INPUT_FLAG_SENSITIVE.
109  * @constant
110  * @type Number
111  */
112 cc.EDITBOX_INPUT_FLAG_PASSWORD = 0;
113 
114 /**
115  * Indicates that the text entered is sensitive data that the
116  * implementation must never store into a dictionary or table for use
117  * in predictive, auto-completing, or other accelerated input schemes.
118  * A credit card number is an example of sensitive data.
119  * @constant
120  * @type Number
121  */
122 cc.EDITBOX_INPUT_FLAG_SENSITIVE = 1;
123 
124 /**
125  * This flag is a hint to the implementation that during text editing,
126  * the initial letter of each word should be capitalized.
127  * @constant
128  * @type Number
129  */
130 cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_WORD = 2;
131 
132 /**
133  * This flag is a hint to the implementation that during text editing,
134  * the initial letter of each sentence should be capitalized.
135  * @constant
136  * @type Number
137  */
138 cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_SENTENCE = 3;
139 
140 /**
141  * Capitalize all characters automatically.
142  * @constant
143  * @type Number
144  */
145 cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_ALL_CHARACTERS = 4;
146 
147 cc.EditBoxDelegate = cc.Class.extend({
148     /**
149      * This method is called when an edit box gains focus after keyboard is shown.
150      * @param {cc.EditBox} sender
151      */
152     editBoxEditingDidBegin: function (sender) {
153     },
154 
155     /**
156      * This method is called when an edit box loses focus after keyboard is hidden.
157      * @param {cc.EditBox} sender
158      */
159     editBoxEditingDidEnd: function (sender) {
160     },
161 
162     /**
163      * This method is called when the edit box text was changed.
164      * @param {cc.EditBox} sender
165      * @param {String} text
166      */
167     editBoxTextChanged: function (sender, text) {
168     },
169 
170     /**
171      * This method is called when the return button was pressed or the outside area of keyboard was touched.
172      * @param {cc.EditBox} sender
173      */
174     editBoxReturn: function (sender) {
175     }
176 });
177 
178 /**
179  * <p>cc.EditBox is a brief Class for edit box.<br/>
180  * You can use this widget to gather small amounts of text from the user.</p>
181  *
182  * @class
183  * @extends cc.ControlButton
184  *
185  * @property {String}   string                  - Content string of edit box
186  * @property {String}   maxLength               - Max length of the content string
187  * @property {String}   font                    - <@writeonly> Config font of edit box
188  * @property {String}   fontName                - <@writeonly> Config font name of edit box
189  * @property {Number}   fontSize                - <@writeonly> Config font size of edit box
190  * @property {cc.Color} fontColor               - <@writeonly> Config font color of edit box
191  * @property {String}   placeHolder             - Place holder of edit box
192  * @property {String}   placeHolderFont         - <@writeonly> Config font of place holder
193  * @property {String}   placeHolderFontName     - <@writeonly> Config font name of place holder
194  * @property {Number}   placeHolderFontSize     - <@writeonly> Config font size of place holder
195  * @property {cc.Color} placeHolderFontColor    - <@writeonly> Config font color of place holder
196  * @property {Number}   inputFlag               - <@writeonly> Input flag of edit box, one of the EditBoxInputFlag constants. e.g.cc.EDITBOX_INPUT_FLAG_PASSWORD
197  * @property {Object}   delegate                - <@writeonly> Delegate of edit box
198  * @property {Number}   inputMode               - <@writeonly> Input mode of the edit box. Value should be one of the EditBoxInputMode constants.
199  * @property {Number}   returnType              - <@writeonly> Return type of edit box, value should be one of the KeyboardReturnType constants.
200  *
201  */
202 cc.EditBox = cc.ControlButton.extend({
203     _domInputSprite: null,
204 
205     _delegate: null,
206     _editBoxInputMode: cc.EDITBOX_INPUT_MODE_ANY,
207     _editBoxInputFlag: cc.EDITBOX_INPUT_FLAG_SENSITIVE,
208     _keyboardReturnType: cc.KEYBOARD_RETURNTYPE_DEFAULT,
209 
210     _text: "",
211     _placeholderText: "",
212     _textColor: null,
213     _placeholderColor: null,
214     _maxLength: 50,
215     _adjustHeight: 18,
216 
217     _edTxt: null,
218     _edFontSize: 14,
219     _edFontName: "Arial",
220 
221     _placeholderFontName: "",
222     _placeholderFontSize: 14,
223 
224     _tooltip: false,
225     _className:"EditBox",
226 
227     /**
228      * * Constructor.
229      * */
230     ctor: function (boxSize) {
231         cc.ControlButton.prototype.ctor.call(this);
232 
233         this._textColor = cc.color.WHITE;
234         this._placeholderColor = cc.color.GRAY;
235         this.setContentSize(boxSize);
236         var tmpDOMSprite = this._domInputSprite = new cc.Sprite();
237         tmpDOMSprite.draw = function(){ };                           //redefine draw function
238         this.addChild(tmpDOMSprite);
239         var selfPointer = this;
240         var tmpEdTxt = this._edTxt = cc.newElement("input");
241         tmpEdTxt.type = "text";
242         tmpEdTxt.style.fontSize = this._edFontSize + "px";
243         tmpEdTxt.style.color = "#000000";
244         tmpEdTxt.style.border = 0;
245         tmpEdTxt.style.background = "transparent";
246         //tmpEdTxt.style.paddingLeft = "2px";
247         tmpEdTxt.style.width = "100%";
248         tmpEdTxt.style.height = "100%";
249         tmpEdTxt.style.active = 0;
250         tmpEdTxt.style.outline = "medium";
251 
252         // TODO the event listener will be remove when EditBox removes from parent.
253         cc._addEventListener(tmpEdTxt, "input", function () {
254             if (selfPointer._delegate && selfPointer._delegate.editBoxTextChanged)
255                 selfPointer._delegate.editBoxTextChanged(selfPointer, this.value);
256         });
257         cc._addEventListener(tmpEdTxt, "keypress", function (e) {
258             if (e.keyCode === cc.KEY.enter) {
259                 e.stopPropagation();
260                 e.preventDefault();
261                 cc._canvas.focus();
262             }
263         });
264         cc._addEventListener(tmpEdTxt, "focus", function () {
265             if (this.value == selfPointer._placeholderText) {
266                 this.value = "";
267                 this.style.fontSize = selfPointer._edFontSize + "px" ;
268                 this.style.color = cc.colorToHex(selfPointer._textColor);
269             }
270             if (selfPointer._delegate && selfPointer._delegate.editBoxEditingDidBegin)
271                 selfPointer._delegate.editBoxEditingDidBegin(selfPointer);
272         });
273         cc._addEventListener(tmpEdTxt, "blur", function () {
274             if (this.value == "") {
275                 this.value = selfPointer._placeholderText;
276                 this.style.fontSize = selfPointer._placeholderFontSize + "px" ;
277                 this.style.color = cc.colorToHex(selfPointer._placeholderColor);
278             }
279             if (selfPointer._delegate && selfPointer._delegate.editBoxEditingDidEnd)
280                 selfPointer._delegate.editBoxEditingDidEnd(selfPointer);
281             if (selfPointer._delegate && selfPointer._delegate.editBoxReturn)
282                 selfPointer._delegate.editBoxReturn(selfPointer);
283         });
284 
285         cc.DOM.convert(tmpDOMSprite);
286         tmpDOMSprite.dom.appendChild(tmpEdTxt);
287         tmpDOMSprite.dom.showTooltipDiv = false;
288         tmpDOMSprite.dom.style.width = (boxSize.width - 6) +"px";
289         tmpDOMSprite.dom.style.height = (boxSize.height - 6) +"px";
290 
291         //this._domInputSprite.dom.style.borderWidth = "1px";
292         //this._domInputSprite.dom.style.borderStyle = "solid";
293         //this._domInputSprite.dom.style.borderRadius = "8px";
294         tmpDOMSprite.canvas.remove();
295     },
296 
297     /**
298      * Set the font.
299      * @param {String} fontName  The font name.
300      * @param {Number} fontSize  The font size.
301      */
302     setFont: function (fontName, fontSize) {
303         this._edFontSize = fontSize;
304         this._edFontName = fontName;
305         this._setFontToEditBox();
306     },
307 
308 	_setFont: function (fontStyle) {
309 		var res = cc.LabelTTF._fontStyleRE.exec(fontStyle);
310 		if(res) {
311 			this._edFontSize = parseInt(res[1]);
312 			this._edFontName = res[2];
313 			this._setFontToEditBox();
314 		}
315 	},
316 
317     /**
318      * set fontName
319      * @param {String} fontName
320      */
321     setFontName: function(fontName){
322         this._edFontName = fontName;
323         this._setFontToEditBox();
324     },
325 
326     /**
327      * set fontSize
328      * @param {Number} fontSize
329      */
330     setFontSize: function(fontSize){
331         this._edFontSize = fontSize;
332         this._setFontToEditBox();
333     },
334 
335     _setFontToEditBox: function () {
336         if (this._edTxt.value != this._placeholderText){
337             this._edTxt.style.fontFamily = this._edFontName;
338             this._edTxt.style.fontSize = this._edFontSize+"px";
339         }
340     },
341 
342     /**
343      *  Set the text entered in the edit box.
344      * @param {string} text The given text.
345      */
346     setText: function (text) {
347         if (text != null) {
348             if (text == "") {
349                 this._edTxt.value = this._placeholderText;
350                 this._edTxt.style.color = cc.colorToHex(this._placeholderColor);
351             } else {
352                 this._edTxt.value = text;
353                 this._edTxt.style.color = cc.colorToHex(this._textColor);
354             }
355         }
356     },
357 
358     /**
359      * Set the font color of the widget's text.
360      * @param {cc.Color} color
361      */
362     setFontColor: function (color) {
363         this._textColor = color;
364         if (this._edTxt.value != this._placeholderText) {
365             this._edTxt.style.color = cc.colorToHex(color);
366         }
367     },
368 
369     /**
370      * <p>
371      * Sets the maximum input length of the edit box. <br/>
372      * Setting this value enables multiline input mode by default.
373      * </p>
374      * @param {Number} maxLength The maximum length.
375      */
376     setMaxLength: function (maxLength) {
377         if (!isNaN(maxLength) && maxLength > 0) {
378             this._maxLength = maxLength;
379             this._edTxt.maxLength = maxLength;
380         }
381     },
382 
383     /**
384      * Gets the maximum input length of the edit box.
385      * @return {Number} Maximum input length.
386      */
387     getMaxLength: function () {
388         return this._maxLength;
389     },
390 
391     /**
392      * Set a text in the edit box that acts as a placeholder when an edit box is empty.
393      * @param {string} text The given text.
394      */
395     setPlaceHolder: function (text) {
396         if (text != null) {
397             var oldPlaceholderText = this._placeholderText;
398             this._placeholderText = text;
399             if (this._edTxt.value == oldPlaceholderText) {
400                 this._edTxt.value = text;
401                 this._edTxt.style.color = cc.colorToHex(this._placeholderColor);
402                 this._setPlaceholderFontToEditText();
403             }
404         }
405     },
406 
407     /**
408      * Set the placeholder's font.
409      * @param {String} fontName
410      * @param {Number} fontSize
411      */
412     setPlaceholderFont: function (fontName, fontSize) {
413         this._placeholderFontName = fontName;
414         this._placeholderFontSize = fontSize;
415         this._setPlaceholderFontToEditText();
416     },
417 	_setPlaceholderFont: function (fontStyle) {
418 		var res = cc.LabelTTF._fontStyleRE.exec(fontStyle);
419 		if(res) {
420 			this._placeholderFontName = res[2];
421 			this._placeholderFontSize = parseInt(res[1]);
422 			this._setPlaceholderFontToEditText();
423 		}
424 	},
425 
426     /**
427      * Set the placeholder's fontName.
428      * @param {String} fontName
429      */
430     setPlaceholderFontName: function (fontName) {
431         this._placeholderFontName = fontName;
432         this._setPlaceholderFontToEditText();
433     },
434 
435     /**
436      * Set the placeholder's fontSize.
437      * @param {Number} fontSize
438      */
439     setPlaceholderFontSize: function (fontSize) {
440         this._placeholderFontSize = fontSize;
441         this._setPlaceholderFontToEditText();
442     },
443 
444     _setPlaceholderFontToEditText: function () {
445         if (this._edTxt.value == this._placeholderText){
446             this._edTxt.style.fontFamily = this._placeholderFontName;
447             this._edTxt.style.fontSize = this._placeholderFontSize + "px";
448         }
449     },
450 
451     /**
452      * Set the font color of the placeholder text when the edit box is empty.
453      * @param {cc.Color} color
454      */
455     setPlaceholderFontColor: function (color) {
456         this._placeholderColor = color;
457         if (this._edTxt.value == this._placeholderText) {
458             this._edTxt.style.color = cc.colorToHex(color);
459         }
460     },
461 
462     /**
463      * Set the input flags that are to be applied to the edit box.
464      * @param {Number} inputFlag One of the EditBoxInputFlag constants.
465      * e.g.cc.EDITBOX_INPUT_FLAG_PASSWORD
466      */
467     setInputFlag: function (inputFlag) {
468         this._editBoxInputFlag = inputFlag;
469         if (inputFlag == cc.EDITBOX_INPUT_FLAG_PASSWORD)
470             this._edTxt.type = "password";
471         else
472             this._edTxt.type = "text";
473     },
474 
475     /**
476      * Gets the  input string of the edit box.
477      * @return {string}
478      */
479     getText: function () {
480         return this._edTxt.value;
481     },
482 
483     /**
484      * Init edit box with specified size.
485      * @param {cc.Size} size
486      * @param {cc.Color | cc.Scale9Sprite} normal9SpriteBg
487      */
488     initWithSizeAndBackgroundSprite: function (size, normal9SpriteBg) {
489         if (this.initWithBackgroundSprite(normal9SpriteBg)) {
490             this._domInputSprite.x = 3;
491 	        this._domInputSprite.y = 3;
492 
493             this.setZoomOnTouchDown(false);
494             this.setPreferredSize(size);
495             this.x = 0;
496 	        this.y = 0;
497             this._addTargetWithActionForControlEvent(this, this.touchDownAction, cc.CONTROL_EVENT_TOUCH_UP_INSIDE);
498             return true;
499         }
500         return false;
501     },
502 
503     /* override functions */
504     /**
505      * Set the delegate for edit box.
506      */
507     setDelegate: function (delegate) {
508         this._delegate = delegate;
509     },
510 
511     /**
512      * Get a text in the edit box that acts as a placeholder when an
513      * edit box is empty.
514      * @return {String}
515      */
516     getPlaceHolder: function () {
517         return this._placeholderText;
518     },
519 
520     /**
521      * Set the input mode of the edit box.
522      * @param {Number} inputMode One of the EditBoxInputMode constants.
523      */
524     setInputMode: function (inputMode) {
525         this._editBoxInputMode = inputMode;
526     },
527 
528     /**
529      * Set the return type that are to be applied to the edit box.
530      * @param {Number} returnType One of the CCKeyboardReturnType constants.
531      */
532     setReturnType: function (returnType) {
533         this._keyboardReturnType = returnType;
534     },
535 
536     keyboardWillShow: function (info) {
537         var rectTracked = cc.EditBox.getRect(this);
538         // some adjustment for margin between the keyboard and the edit box.
539         rectTracked.y -= 4;
540         // if the keyboard area doesn't intersect with the tracking node area, nothing needs to be done.
541         if (!rectTracked.intersectsRect(info.end)) {
542             cc.log("needn't to adjust view layout.");
543             return;
544         }
545 
546         // assume keyboard at the bottom of screen, calculate the vertical adjustment.
547         this._adjustHeight = info.end.getMaxY() - rectTracked.getMinY();
548         // CCLOG("CCEditBox:needAdjustVerticalPosition(%f)", m_fAdjustHeight);
549 
550         //callback
551     },
552     keyboardDidShow: function (info) {
553     },
554     keyboardWillHide: function (info) {
555         //if (m_pEditBoxImpl != NULL) {
556         //    m_pEditBoxImpl->doAnimationWhenKeyboardMove(info.duration, -m_fAdjustHeight);
557         //}
558     },
559     keyboardDidHide: function (info) {
560     },
561 
562     touchDownAction: function (sender, controlEvent) {
563         //this._editBoxImpl.openKeyboard();
564     },
565 
566     //HTML5 Only
567     initWithBackgroundColor: function (size, bgColor) {
568         this._edWidth = size.width;
569         this.dom.style.width = this._edWidth.toString() + "px";
570         this._edHeight = size.height;
571         this.dom.style.height = this._edHeight.toString() + "px";
572         this.dom.style.backgroundColor = cc.colorToHex(bgColor);
573     }
574 });
575 
576 window._p = cc.EditBox.prototype;
577 
578 // Extended properties
579 /** @expose */
580 _p.font;
581 cc.defineGetterSetter(_p, "font", null, _p._setFont);
582 /** @expose */
583 _p.fontName;
584 cc.defineGetterSetter(_p, "fontName", null, _p.setFontName);
585 /** @expose */
586 _p.fontSize;
587 cc.defineGetterSetter(_p, "fontSize", null, _p.setFontSize);
588 /** @expose */
589 _p.fontColor;
590 cc.defineGetterSetter(_p, "fontColor", null, _p.setFontColor);
591 /** @expose */
592 _p.string;
593 cc.defineGetterSetter(_p, "string", _p.getText, _p.setText);
594 /** @expose */
595 _p.maxLength;
596 cc.defineGetterSetter(_p, "maxLength", _p.getMaxLength, _p.setMaxLength);
597 /** @expose */
598 _p.placeHolder;
599 cc.defineGetterSetter(_p, "placeHolder", _p.getPlaceHolder, _p.setPlaceHolder);
600 /** @expose */
601 _p.placeHolderFont;
602 cc.defineGetterSetter(_p, "placeHolderFont", null, _p._setPlaceholderFont);
603 /** @expose */
604 _p.placeHolderFontName;
605 cc.defineGetterSetter(_p, "placeHolderFontName", null, _p.setPlaceholderFontName);
606 /** @expose */
607 _p.placeHolderFontSize;
608 cc.defineGetterSetter(_p, "placeHolderFontSize", null, _p.setPlaceholderFontSize);
609 /** @expose */
610 _p.placeHolderFontColor;
611 cc.defineGetterSetter(_p, "placeHolderFontColor", null, _p.setPlaceholderFontColor);
612 /** @expose */
613 _p.inputFlag;
614 cc.defineGetterSetter(_p, "inputFlag", null, _p.setInputFlag);
615 /** @expose */
616 _p.delegate;
617 cc.defineGetterSetter(_p, "delegate", null, _p.setDelegate);
618 /** @expose */
619 _p.inputMode;
620 cc.defineGetterSetter(_p, "inputMode", null, _p.setInputMode);
621 /** @expose */
622 _p.returnType;
623 cc.defineGetterSetter(_p, "returnType", null, _p.setReturnType);
624 
625 delete window._p;
626 
627 cc.EditBox.getRect = function (node) {
628     var contentSize = node.getContentSize();
629     var rect = cc.rect(0, 0, contentSize.width, contentSize.height);
630     return cc.RectApplyAffineTransform(rect, node.nodeToWorldTransform());
631 };
632 
633 /**
634  * create a edit box with size and background-color or
635  * @param {cc.Size} size
636  * @param {cc.Scale9Sprite } normal9SpriteBg
637  * @param {cc.Scale9Sprite } [press9SpriteBg]
638  * @param {cc.Scale9Sprite } [disabled9SpriteBg]
639  */
640 cc.EditBox.create = function (size, normal9SpriteBg, press9SpriteBg, disabled9SpriteBg) {
641     var edbox = new cc.EditBox(size);
642     if (edbox.initWithSizeAndBackgroundSprite(size, normal9SpriteBg)) {
643         if (press9SpriteBg)
644             edbox.setBackgroundSpriteForState(press9SpriteBg, cc.CONTROL_STATE_HIGHLIGHTED);
645 
646         if (disabled9SpriteBg)
647             edbox.setBackgroundSpriteForState(disabled9SpriteBg, cc.CONTROL_STATE_DISABLED);
648     }
649     return edbox;
650 };
651 
652 
653 
654 
655