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  * brief Class for edit box.
180  *
181  * You can use this widget to gather small amounts of text from the user.
182  *
183  */
184 cc.EditBox = cc.ControlButton.extend({
185     _domInputSprite: null,
186 
187     _delegate: null,
188     _editBoxInputMode: cc.EDITBOX_INPUT_MODE_ANY,
189     _editBoxInputFlag: cc.EDITBOX_INPUT_FLAG_SENSITIVE,
190     _keyboardReturnType: cc.KEYBOARD_RETURNTYPE_DEFAULT,
191 
192     _text: "",
193     _placeholderText: "",
194     _textColor: null,
195     _placeholderColor: null,
196     _maxLength: 50,
197     _adjustHeight: 18,
198 
199     _edTxt: null,
200     _edFontSize: 14,
201     _edFontName: "Arial",
202 
203     _placeholderFontName: "",
204     _placeholderFontSize: 14,
205 
206     _tooltip: false,
207 
208     /**
209      * * Constructor.
210      * */
211     ctor: function (boxSize) {
212         cc.ControlButton.prototype.ctor.call(this);
213 
214         this._textColor = cc.white();
215         this._placeholderColor = cc.gray();
216         this.setContentSize(boxSize);
217         this._domInputSprite = new cc.Sprite();
218         this._domInputSprite.draw = function(){ };                           //redefine draw function
219         this.addChild(this._domInputSprite);
220         var selfPointer = this;
221         this._edTxt = document.createElement("input");
222         this._edTxt.type = "text";
223         this._edTxt.style.fontSize = this._edFontSize + "px";
224         this._edTxt.style.color = "#000000";
225         this._edTxt.style.border = 0;
226         this._edTxt.style.background = "transparent";
227         //this._edTxt.style.paddingLeft = "2px";
228         this._edTxt.style.width = "100%";
229         this._edTxt.style.height = "100%";
230         this._edTxt.style.active = 0;
231         this._edTxt.style.outline = "medium";
232 
233         // TODO the event listener will be remove when EditBox removes from parent.
234         this._edTxt.addEventListener("input", function () {
235             if (selfPointer._delegate && selfPointer._delegate.editBoxTextChanged)
236                 selfPointer._delegate.editBoxTextChanged(selfPointer, this.value);
237         });
238         this._edTxt.addEventListener("keypress", function (e) {
239             if (e.keyCode === cc.KEY.enter) {
240                 e.stopPropagation();
241                 e.preventDefault();
242                 cc.canvas.focus();
243             }
244         });
245         this._edTxt.addEventListener("focus", function () {
246             if (this.value == selfPointer._placeholderText) {
247                 this.value = "";
248                 this.style.fontSize = selfPointer._edFontSize + "px" ;
249                 this.style.color = cc.convertColor3BtoHexString(selfPointer._textColor);
250             }
251             if (selfPointer._delegate && selfPointer._delegate.editBoxEditingDidBegin)
252                 selfPointer._delegate.editBoxEditingDidBegin(selfPointer);
253         });
254         this._edTxt.addEventListener("blur", function () {
255             if (this.value == "") {
256                 this.value = selfPointer._placeholderText;
257                 this.style.fontSize = selfPointer._placeholderFontSize + "px" ;
258                 this.style.color = cc.convertColor3BtoHexString(selfPointer._placeholderColor);
259             }
260             if (selfPointer._delegate && selfPointer._delegate.editBoxEditingDidEnd)
261                 selfPointer._delegate.editBoxEditingDidEnd(selfPointer);
262             if (selfPointer._delegate && selfPointer._delegate.editBoxReturn)
263                 selfPointer._delegate.editBoxReturn(selfPointer);
264         });
265 
266         cc.DOM.convert(this._domInputSprite);
267         this._domInputSprite.dom.appendChild(this._edTxt);
268         this._domInputSprite.dom.showTooltipDiv = false;
269         this._domInputSprite.dom.style.width = (boxSize.width - 6) +"px";
270         this._domInputSprite.dom.style.height = (boxSize.height - 6) +"px";
271 
272         //this._domInputSprite.dom.style.borderWidth = "1px";
273         //this._domInputSprite.dom.style.borderStyle = "solid";
274         //this._domInputSprite.dom.style.borderRadius = "8px";
275         this._domInputSprite.canvas.remove();
276     },
277 
278     /**
279      * Set the font.
280      * @param {String} fontName  The font name.
281      * @param {Number} fontSize  The font size.
282      */
283     setFont: function (fontName, fontSize) {
284         this._edFontSize = fontSize;
285         this._edFontName = fontName;
286         this._setFontToEditBox();
287     },
288 
289     /**
290      * set fontName
291      * @param {String} fontName
292      */
293     setFontName: function(fontName){
294         this._edFontName = fontName;
295         this._setFontToEditBox();
296     },
297 
298     /**
299      * set fontSize
300      * @param {Number} fontSize
301      */
302     setFontSize: function(fontSize){
303         this._edFontSize = fontSize;
304         this._setFontToEditBox();
305     },
306 
307     _setFontToEditBox: function () {
308         if (this._edTxt.value != this._placeholderText){
309             this._edTxt.style.fontFamily = this._edFontName;
310             this._edTxt.style.fontSize = this._edFontSize+"px";
311         }
312     },
313 
314     /**
315      *  Set the text entered in the edit box.
316      * @param {string} text The given text.
317      */
318     setText: function (text) {
319         if (text != null) {
320             if (text == "") {
321                 this._edTxt.value = this._placeholderText;
322                 this._edTxt.style.color = cc.convertColor3BtoHexString(this._placeholderColor);
323             } else {
324                 this._edTxt.value = text;
325                 this._edTxt.style.color = cc.convertColor3BtoHexString(this._textColor);
326             }
327         }
328     },
329 
330     /**
331      * Set the font color of the widget's text.
332      * @param {cc.Color3B} color
333      */
334     setFontColor: function (color) {
335         this._textColor = color;
336         if (this._edTxt.value != this._placeholderText) {
337             this._edTxt.style.color = cc.convertColor3BtoHexString(color);
338         }
339     },
340 
341     /**
342      * <p>
343      * Sets the maximum input length of the edit box. <br/>
344      * Setting this value enables multiline input mode by default.
345      * </p>
346      * @param {Number} maxLength The maximum length.
347      */
348     setMaxLength: function (maxLength) {
349         if (!isNaN(maxLength) && maxLength > 0) {
350             this._maxLength = maxLength;
351             this._edTxt.maxLength = maxLength;
352         }
353     },
354 
355     /**
356      * Gets the maximum input length of the edit box.
357      * @return {Number} Maximum input length.
358      */
359     getMaxLength: function () {
360         return this._maxLength;
361     },
362 
363     /**
364      * Set a text in the edit box that acts as a placeholder when an edit box is empty.
365      * @param {string} text The given text.
366      */
367     setPlaceHolder: function (text) {
368         if (text != null) {
369             var oldPlaceholderText = this._placeholderText;
370             this._placeholderText = text;
371             if (this._edTxt.value == oldPlaceholderText) {
372                 this._edTxt.value = text;
373                 this._edTxt.style.color = cc.convertColor3BtoHexString(this._placeholderColor);
374                 this._setPlaceholderFontToEditText();
375             }
376         }
377     },
378 
379     /**
380      * Set the placeholder's font.
381      * @param {String} fontName
382      * @param {Number} fontSize
383      */
384     setPlaceholderFont: function (fontName, fontSize) {
385         this._placeholderFontName = fontName;
386         this._placeholderFontSize = fontSize;
387         this._setPlaceholderFontToEditText();
388     },
389 
390     /**
391      * Set the placeholder's fontName.
392      * @param {String} fontName
393      */
394     setPlaceholderFontName: function (fontName) {
395         this._placeholderFontName = fontName;
396         this._setPlaceholderFontToEditText();
397     },
398 
399     /**
400      * Set the placeholder's fontSize.
401      * @param {Number} fontSize
402      */
403     setPlaceholderFontSize: function (fontSize) {
404         this._placeholderFontSize = fontSize;
405         this._setPlaceholderFontToEditText();
406     },
407 
408     _setPlaceholderFontToEditText: function () {
409         if (this._edTxt.value == this._placeholderText){
410             this._edTxt.style.fontFamily = this._placeholderFontName;
411             this._edTxt.style.fontSize = this._placeholderFontSize + "px";
412         }
413     },
414 
415     /**
416      * Set the font color of the placeholder text when the edit box is empty.
417      * @param {cc.Color3B} color
418      */
419     setPlaceholderFontColor: function (color) {
420         this._placeholderColor = color;
421         if (this._edTxt.value == this._placeholderText) {
422             this._edTxt.style.color = cc.convertColor3BtoHexString(color);
423         }
424     },
425 
426     /**
427      * Set the input flags that are to be applied to the edit box.
428      * @param {Number} inputFlag One of the EditBoxInputFlag constants.
429      * e.g.cc.EDITBOX_INPUT_FLAG_PASSWORD
430      */
431     setInputFlag: function (inputFlag) {
432         this._editBoxInputFlag = inputFlag;
433         if (inputFlag == cc.EDITBOX_INPUT_FLAG_PASSWORD)
434             this._edTxt.type = "password";
435         else
436             this._edTxt.type = "text";
437     },
438 
439     /**
440      * Gets the  input string of the edit box.
441      * @return {string}
442      */
443     getText: function () {
444         return this._edTxt.value;
445     },
446 
447     /**
448      * Init edit box with specified size.
449      * @param {cc.Size} size
450      * @param {cc.Color3B | cc.Scale9Sprite} normal9SpriteBg
451      */
452     initWithSizeAndBackgroundSprite: function (size, normal9SpriteBg) {
453         if (this.initWithBackgroundSprite(normal9SpriteBg)) {
454             this._domInputSprite.setPosition(3, 3);
455 
456             this.setZoomOnTouchDown(false);
457             this.setPreferredSize(size);
458             this.setPosition(0, 0);
459             this._addTargetWithActionForControlEvent(this, this.touchDownAction, cc.CONTROL_EVENT_TOUCH_UP_INSIDE);
460             return true;
461         }
462         return false;
463     },
464 
465     /* override functions */
466     /**
467      * Set the delegate for edit box.
468      */
469     setDelegate: function (delegate) {
470         this._delegate = delegate;
471     },
472 
473     /**
474      * Get a text in the edit box that acts as a placeholder when an
475      * edit box is empty.
476      * @return {String}
477      */
478     getPlaceHolder: function () {
479         return this._placeholderText;
480     },
481 
482     /**
483      * Set the input mode of the edit box.
484      * @param {Number} inputMode One of the EditBoxInputMode constants.
485      */
486     setInputMode: function (inputMode) {
487         this._editBoxInputMode = inputMode;
488     },
489 
490     /**
491      * Set the return type that are to be applied to the edit box.
492      * @param {Number} returnType One of the CCKeyboardReturnType constants.
493      */
494     setReturnType: function (returnType) {
495         this._keyboardReturnType = returnType;
496     },
497 
498     keyboardWillShow: function (info) {
499         var rectTracked = cc.EditBox.getRect(this);
500         // some adjustment for margin between the keyboard and the edit box.
501         rectTracked.y -= 4;
502         // if the keyboard area doesn't intersect with the tracking node area, nothing needs to be done.
503         if (!rectTracked.intersectsRect(info.end)) {
504             cc.log("needn't to adjust view layout.");
505             return;
506         }
507 
508         // assume keyboard at the bottom of screen, calculate the vertical adjustment.
509         this._adjustHeight = info.end.getMaxY() - rectTracked.getMinY();
510         // CCLOG("CCEditBox:needAdjustVerticalPosition(%f)", m_fAdjustHeight);
511 
512         //callback
513     },
514     keyboardDidShow: function (info) {
515     },
516     keyboardWillHide: function (info) {
517         //if (m_pEditBoxImpl != NULL) {
518         //    m_pEditBoxImpl->doAnimationWhenKeyboardMove(info.duration, -m_fAdjustHeight);
519         //}
520     },
521     keyboardDidHide: function (info) {
522     },
523 
524     touchDownAction: function (sender, controlEvent) {
525         //this._editBoxImpl.openKeyboard();
526     },
527 
528     //HTML5 Only
529     initWithBackgroundColor: function (size, bgColor) {
530         this._edWidth = size.width;
531         this.dom.style.width = this._edWidth.toString() + "px";
532         this._edHeight = size.height;
533         this.dom.style.height = this._edHeight.toString() + "px";
534         this.dom.style.backgroundColor = cc.convertColor3BtoHexString(bgColor);
535     }
536 });
537 
538 cc.EditBox.getRect = function (node) {
539     var contentSize = node.getContentSize();
540     var rect = cc.rect(0, 0, contentSize.width, contentSize.height);
541     return cc.RectApplyAffineTransform(rect, node.nodeToWorldTransform());
542 };
543 
544 /**
545  * create a edit box with size and background-color or
546  * @param {cc.Size} size
547  * @param {cc.Color3B | cc.Scale9Sprite } normal9SpriteBg
548  */
549 cc.EditBox.create = function (size, normal9SpriteBg, press9SpriteBg, disabled9SpriteBg) {
550     var edbox = new cc.EditBox(size);
551     if (normal9SpriteBg instanceof cc.Color3B) {
552         edbox.setBackgroundColor(normal9SpriteBg);
553     } else {
554         //Todo
555         if (edbox.initWithSizeAndBackgroundSprite(size, normal9SpriteBg)) {
556             if (press9SpriteBg)
557                 edbox.setBackgroundSpriteForState(press9SpriteBg, cc.CONTROL_STATE_HIGHLIGHTED);
558 
559             if (disabled9SpriteBg)
560                 edbox.setBackgroundSpriteForState(disabled9SpriteBg, cc.CONTROL_STATE_DISABLED);
561         }
562     }
563     return edbox;
564 };
565 
566 
567 
568 
569