1 // ========================================================================== 2 // Project: The M-Project - Mobile HTML5 Application Framework 3 // Copyright: (c) 2010 M-Way Solutions GmbH. All rights reserved. 4 // (c) 2011 panacoda GmbH. All rights reserved. 5 // Creator: Dominik 6 // Date: 26.11.2010 7 // License: Dual licensed under the MIT or GPL Version 2 licenses. 8 // http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE 9 // http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE 10 // ========================================================================== 11 12 /** 13 * @class 14 * 15 * M.SearchBarView defines a prototype of a search bar that can be used inside of a list 16 * view or independently as a plain input field with a search styling. 17 * 18 * @extends M.View 19 */ 20 M.SearchBarView = M.View.extend( 21 /** @scope M.SearchBarView.prototype */ { 22 23 /** 24 * The type of this object. 25 * 26 * @type String 27 */ 28 type: 'M.SearchBarView', 29 30 /** 31 * Determines whether the search bar is part of a list view. 32 * 33 * @type Boolean 34 */ 35 isListViewSearchBar: NO, 36 37 /** 38 * If the search bar belongs to a list view, this property contains this 39 * list view. 40 * 41 * @type M.ListView 42 */ 43 listView: null, 44 45 /** 46 * The initial text shown inside the search bar field describing the input or making a suggestion for 47 * input e.g. "Please enter your Name." 48 * 49 * @type String 50 */ 51 initialText: '', 52 53 /** 54 * This property specifies the recommended events for this type of view. 55 * 56 * @type Array 57 */ 58 recommendedEvents: ['focus', 'blur', 'enter', 'keyup'], 59 60 /** 61 * Renders a search bar. 62 * 63 * @private 64 * @returns {String} The search bar view's html representation. 65 */ 66 render: function() { 67 this.html += '<form role="search"' + this.style() + '>'; 68 69 this.html += '<input id="' + this.id + '" type="search" value="' + (this.value ? this.value : this.initialText) + '" class="' + this.cssClass + '" />'; 70 71 this.html += '</form>'; 72 73 return this.html; 74 }, 75 76 /** 77 * This method is responsible for registering events for view elements and its child views. It 78 * basically passes the view's event-property to M.EventDispatcher to bind the appropriate 79 * events. 80 * 81 * It extend M.View's registerEvents method with some special stuff for text field views and 82 * their internal events. 83 */ 84 registerEvents: function() { 85 this.internalEvents = { 86 focus: { 87 target: this, 88 action: 'gotFocus' 89 }, 90 blur: { 91 target: this, 92 action: 'lostFocus' 93 }, 94 keyup: { 95 target: this, 96 action: 'setValueFromDOM' 97 } 98 } 99 this.bindToCaller(this, M.View.registerEvents)(); 100 }, 101 102 /** 103 * Updates a SearchBarView with DOM access by jQuery. 104 * 105 * @private 106 */ 107 renderUpdate: function() { 108 $('#' + this.id).val(this.value); 109 this.styleUpdate(); 110 }, 111 112 /** 113 * This method sets its value to the value it has in its DOM representation 114 * and then delegates these changes to a controller property if the 115 * contentBindingReverse property is set. 116 * 117 * Additionally call target / action if set. 118 * 119 * @param {Object} evt The event triggered this method. 120 */ 121 setValueFromDOM: function(id, event, nextEvent) { 122 this.value = this.secure($('#' + this.id).val()); 123 this.delegateValueUpdate(); 124 125 if(nextEvent) { 126 M.EventDispatcher.callHandler(nextEvent, event, YES); 127 } 128 }, 129 130 /** 131 * Applies some style-attributes to the button. 132 * 133 * @private 134 * @returns {String} The search bar's styling as html representation. 135 */ 136 style: function() { 137 var html = ''; 138 if(this.isListViewSearchBar) { 139 html += ' class="ui-listview-filter"'; 140 } 141 return html; 142 }, 143 144 /** 145 * Method to append css styles inline to the rendered view on the fly. 146 * 147 * @private 148 */ 149 styleUpdate: function() { 150 if(this.isInline) { 151 $('#' + this.id).attr('display', 'inline'); 152 } else { 153 $('#' + this.id).removeAttr('display'); 154 } 155 156 if(!this.isEnabled) { 157 $('#' + this.id).attr('disabled', 'disabled'); 158 } else { 159 $('#' + this.id).removeAttr('disabled'); 160 } 161 }, 162 163 /** 164 * This method is called whenever the view gets the focus. 165 * If there is a initial text specified and the value of this search bar field 166 * still equals this initial text, the value is emptied. 167 */ 168 gotFocus: function() { 169 if(this.initialText && (!this.value || this.initialText === this.value)) { 170 this.setValue(''); 171 if(this.cssClassOnInit) { 172 this.removeCssClass(this.cssClassOnInit); 173 } 174 } 175 this.hasFocus = YES; 176 }, 177 178 /** 179 * This method is called whenever the view lost the focus. 180 * If there is a initial text specified and the value of this search bar field 181 * is empty, the value is set to the initial text. 182 */ 183 lostFocus: function() { 184 if(this.initialText && !this.value) { 185 this.setValue(this.initialText, NO); 186 this.value = ''; 187 if(this.cssClassOnInit) { 188 this.addCssClass(this.cssClassOnInit); 189 } 190 } 191 this.hasFocus = NO; 192 }, 193 194 /** 195 * This method sets the text field's value, initiates its re-rendering 196 * and call the delegateValueUpdate(). 197 * 198 * @param {String} value The value to be applied to the text field view. 199 * @param {Boolean} delegateUpdate Determines whether to delegate this value update to any observer or not. 200 */ 201 setValue: function(value, delegateUpdate) { 202 this.value = value; 203 this.renderUpdate(); 204 205 if(delegateUpdate) { 206 this.delegateValueUpdate(); 207 } 208 }, 209 210 /** 211 * This method disables the search bar by setting the disabled property of its 212 * html representation to true. 213 */ 214 disable: function() { 215 this.isEnabled = NO; 216 this.renderUpdate(); 217 }, 218 219 /** 220 * This method enables the search bar by setting the disabled property of its 221 * html representation to false. 222 */ 223 enable: function() { 224 this.isEnabled = YES; 225 this.renderUpdate(); 226 }, 227 228 /** 229 * This method clears the search bar's value, both in the DOM and within the JS object. 230 */ 231 clearValue: function() { 232 this.setValue(''); 233 234 /* call lostFocus() to get the initial text displayed */ 235 this.lostFocus(); 236 }, 237 238 /** 239 * Triggers the rendering engine, jQuery mobile, to style the search bar field. 240 * 241 * @private 242 */ 243 theme: function() { 244 if(this.initialText && !this.value && this.cssClassOnInit) { 245 this.addCssClass(this.cssClassOnInit); 246 } 247 248 /* register tap event for delete button */ 249 var that = this; 250 $('#' + this.id).siblings('a.ui-input-clear').bind('tap', function() { 251 that.setValue('', YES); 252 }); 253 }, 254 255 /** 256 * This method returns the search bar view's value. 257 * 258 * @returns {String} The search bar view's value. 259 */ 260 getValue: function() { 261 return this.value; 262 } 263 264 });