1 // ========================================================================== 2 // Project: The M-Project - Mobile HTML5 Application Framework 3 // Copyright: (c) 2010 M-Way Solutions GmbH. All rights reserved. 4 // Creator: Sebastian 5 // Date: 04.11.2010 6 // License: Dual licensed under the MIT or GPL Version 2 licenses. 7 // http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE 8 // http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE 9 // ========================================================================== 10 11 /** 12 * @class 13 * 14 * M.TextFieldView is the prototype of any text field input view. It can be rendered as both 15 * a single line text field and a multiple line text field. If it is styled as a multiple 16 * line text field, is has a built-in autogrow mechanism so the textfield is getting larger 17 * depending on the number of lines of text a user enters. 18 * 19 * @extends M.View 20 */ 21 M.TextFieldView = M.View.extend( 22 /** @scope M.TextFieldView.prototype */ { 23 24 /** 25 * The type of this object. 26 * 27 * @type String 28 */ 29 type: 'M.TextFieldView', 30 31 /** 32 * The name of the text field. During the rendering, this property gets assigned to the name 33 * property of the text field's html representation. This can be used to manually access the 34 * text field's DOM representation later on. 35 * 36 * @type String 37 */ 38 name: null, 39 40 /** 41 * The label proeprty defines a text that is shown above or next to the textfield as a 'title' 42 * for the textfield. e.g. "Name:". If no label is specified, no label will be displayed. 43 * 44 * @type String 45 */ 46 label: null, 47 48 /** 49 * The initial text shown inside the text field describing the input or making a suggestion for input 50 * e.g. "Please enter your Name." 51 * 52 * @type String 53 */ 54 initialText: '', 55 56 /** 57 * Defines whether the text field is rendered as an password field or not. 58 * 59 * @type Boolean 60 */ 61 isPassword: NO, 62 63 /** 64 * Defines whether the text field has multiple lines respectively is a text area. 65 * 66 * @type Boolean 67 */ 68 hasMultipleLines: NO, 69 70 /** 71 * Renders a TextFieldView 72 * 73 * @private 74 * @returns {String} The text field view's html representation. 75 */ 76 render: function() { 77 this.html += '<div ' + this.style() + ' data-role="fieldcontain">'; 78 79 if(this.label) { 80 this.html += '<label for="' + (this.name ? this.name : this.id) + '">' + this.label + '</label>'; 81 } 82 83 var type = this.isPassword ? 'password' : 'text'; 84 85 if(this.hasMultipleLines) { 86 this.html += '<textarea cols="40" rows="8" name="' + (this.name ? this.name : this.id) + '" id="' + this.id + '">' + (this.value ? this.value : this.initialText) + '</textarea>'; 87 88 } else { 89 this.html += '<input type="' + type + '" name="' + (this.name ? this.name : this.id) + '" id="' + this.id + '" value="' + (this.value ? this.value : this.initialText) + '" />'; 90 } 91 92 this.html += '</div>'; 93 94 return this.html; 95 }, 96 97 /** 98 * Updates a TextFieldView with DOM access by jQuery. 99 * 100 * @private 101 */ 102 renderUpdate: function() { 103 $('#' + this.id).val(this.value); 104 this.styleUpdate(); 105 }, 106 107 /** 108 * This method is called whenever the view gets the focus. 109 * If there is a initial text specified and the value of this text field 110 * still equals this initial text, the value is emptied. 111 */ 112 gotFocus: function() { 113 if(this.initialText && (!this.value || this.initialText === this.value)) { 114 this.setValue(''); 115 if(this.cssClassOnInit) { 116 this.removeCssClass(this.cssClassOnInit); 117 } 118 } 119 this.hasFocus = YES; 120 }, 121 122 /** 123 * This method is called whenever the view lost the focus. 124 * If there is a initial text specified and the value of this text field 125 * is empty, the value is set to the initial text. 126 */ 127 lostFocus: function() { 128 if(this.initialText && !this.value) { 129 this.setValue(this.initialText, NO); 130 this.value = ''; 131 if(this.cssClassOnInit) { 132 this.addCssClass(this.cssClassOnInit); 133 } 134 } 135 this.hasFocus = NO; 136 }, 137 138 /** 139 * Method to append css styles inline to the rendered text field. 140 * 141 * @private 142 * @returns {String} The text field's styling as html representation. 143 */ 144 style: function() { 145 var html = ''; 146 if(this.isInline) { 147 if(!html) { 148 html += 'style="'; 149 } 150 html += 'display:inline;'; 151 } 152 if(!this.isEnabled) { 153 if(!html) { 154 html += 'style="'; 155 } 156 html += 'disabled="disabled"'; 157 } 158 if(html) { 159 html += '"'; 160 } 161 return html; 162 }, 163 164 /** 165 * Triggers the rendering engine, jQuery mobile, to style the text field. 166 * 167 * @private 168 */ 169 theme: function() { 170 if(this.initialText && !this.value && this.cssClassOnInit) { 171 this.addCssClass(this.cssClassOnInit); 172 } 173 }, 174 175 /** 176 * Method to append css styles inline to the rendered view on the fly. 177 * 178 * @private 179 */ 180 styleUpdate: function() { 181 if(this.isInline) { 182 $('#' + this.id).attr('display', 'inline'); 183 } else { 184 $('#' + this.id).removeAttr('display'); 185 } 186 187 if(!this.isEnabled) { 188 $('#' + this.id).attr('disabled', 'disabled'); 189 } else { 190 $('#' + this.id).removeAttr('disabled'); 191 } 192 }, 193 194 /** 195 * This method sets its value to the value it has in its DOM representation 196 * and then delegates these changes to a controller property if the 197 * contentBindingReverse property is set. 198 * 199 * Additionally call target / action if set. 200 * 201 * @param {Object} evt The event triggered this method. 202 */ 203 setValueFromDOM: function(evt) { 204 this.value = this.secure($('#' + this.id).val()); 205 this.delegateValueUpdate(); 206 207 if((evt === 'change' && this.triggerActionOnChange || evt === 'keyup' && this.triggerActionOnKeyUp) && this.target && this.action) { 208 this.target[this.action](this.value); 209 } 210 }, 211 212 /** 213 * This method sets the text field's value, initiates its re-rendering 214 * and call the delegateValueUpdate(). 215 * 216 * @param {String} value The value to be applied to the text field view. 217 * @param {Boolean} delegateUpdate Determines whether to delegate this value update to any observer or not. 218 */ 219 setValue: function(value, delegateUpdate) { 220 this.value = value; 221 this.renderUpdate(); 222 223 if(delegateUpdate) { 224 this.delegateValueUpdate(); 225 } 226 }, 227 228 /** 229 * This method disables the text field by setting the disabled property of its 230 * html representation to true. 231 */ 232 disable: function() { 233 this.isEnabled = NO; 234 this.renderUpdate(); 235 }, 236 237 /** 238 * This method enables the text field by setting the disabled property of its 239 * html representation to false. 240 */ 241 enable: function() { 242 this.isEnabled = YES; 243 this.renderUpdate(); 244 } 245 246 });