1 // ========================================================================== 2 // Project: The M-Project - Mobile HTML5 Application Framework 3 // Copyright: (c) 2010 M-Way Solutions GmbH. All rights reserved. 4 // Creator: Dominik 5 // Date: 30.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 * A constant value for single selection mode. 13 * 14 * @type String 15 */ 16 M.SINGLE_SELECTION = 'radio'; 17 18 /** 19 * A constant value for multiple selection mode. 20 * 21 * @type String 22 */ 23 M.MULTIPLE_SELECTION = 'checkbox'; 24 25 m_require('ui/selection_list_item.js'); 26 27 /** 28 * @class 29 * 30 * This defines the prototype of any selection list view. A selection list view displays 31 * a list with several items of which either only one single item (M.SINGLE_SELECTION) or 32 * many items (M.MULTIPLE_SELECTION) can be selected. 33 * 34 * @extends M.View 35 */ 36 M.SelectionListView = M.View.extend( 37 /** @scope M.SelectionListView.prototype */ { 38 39 /** 40 * The type of this object. 41 * 42 * @type String 43 */ 44 type: 'M.SelectionListView', 45 46 /** 47 * Determines whether to remove all item if the list is updated or not. 48 * 49 * @type Boolean 50 */ 51 removeItemsOnUpdate: YES, 52 53 /** 54 * The selection mode for this selection list. This can either be single or 55 * multiple selection. To set this value use one of the two constants: 56 * 57 * - M.SINGLE_SELECTION 58 * - M.MULTIPLE_SELECTION 59 * 60 * @type String 61 */ 62 selectionMode: M.SINGLE_SELECTION, 63 64 /** 65 * This property is used to define a method that is executed onSelect of an 66 * item of this selection list. 67 * 68 * @type Object 69 */ 70 onSelect: null, 71 72 /** 73 * The selected item(s) of this list. 74 * 75 * @type String, Array 76 */ 77 selection: null, 78 79 /** 80 * Renders a selection list. 81 * 82 * @private 83 * @returns {String} The selection list view's html representation. 84 */ 85 render: function() { 86 this.html += '<fieldset data-role="controlgroup" id="' + this.id + '">'; 87 88 if(this.label) { 89 this.html += '<legend>' + this.label + '</legend>'; 90 } 91 92 this.renderChildViews(); 93 94 this.html += '</fieldset>'; 95 96 return this.html; 97 }, 98 99 /** 100 * Triggers render() on all children of type M.ButtonView based on the specified 101 * selection mode (single or multiple selection). 102 * 103 * @private 104 */ 105 renderChildViews: function() { 106 if(this.childViews) { 107 var childViews = $.trim(this.childViews).split(' '); 108 for(var i in childViews) { 109 var view = this[childViews[i]]; 110 if(view.type === 'M.SelectionListItemView') { 111 view.parentView = this; 112 view.internalTarget = this; 113 view.internalAction = 'itemSelected'; 114 this.html += view.render(); 115 } else { 116 M.Logger.log('Invalid child views specified for SelectionListView. Only SelectionListItemViews accepted.', M.WARN); 117 } 118 } 119 } else if(!this.contentBinding) { 120 M.Logger.log('No SelectionListItemViews specified.', M.WARN); 121 } 122 }, 123 124 /** 125 * This method adds a new selection list item to the selection list view by simply appending 126 * its html representation to the selection list view inside the DOM. This method is based 127 * on jQuery's append(). 128 * 129 * @param {String} item The html representation of a selection list item to be added. 130 */ 131 addItem: function(item) { 132 $('#' + this.id).append(item); 133 }, 134 135 /** 136 * This method removes all of the selection list view's items by removing all of its content in 137 * the DOM. This method is based on jQuery's empty(). 138 */ 139 removeAllItems: function() { 140 $('#' + this.id).empty(); 141 }, 142 143 /** 144 * Updates the the selection list view by re-rendering all of its child views, respectively its 145 * item views. 146 * 147 * @private 148 */ 149 renderUpdate: function() { 150 if(this.removeItemsOnUpdate) { 151 this.removeAllItems(); 152 153 if(this.label) { 154 this.addItem('<legend>' + this.label + '</legend>'); 155 } 156 } 157 158 if(this.contentBinding) { 159 var items = eval(this.contentBinding); 160 for(var i in items) { 161 var item = items[i]; 162 var obj = M.SelectionListItemView.design({ 163 value: item.value, 164 label: item.label, 165 name: item.name, 166 isSelected: item.isSelected, 167 parentView: this, 168 internalTarget: this, 169 internalAction: 'itemSelected' 170 }); 171 this.addItem(obj.render()); 172 obj.theme() 173 } 174 this.theme(); 175 } 176 }, 177 178 /** 179 * Triggers the rendering engine, jQuery mobile, to style the selection list. 180 * 181 * @private 182 */ 183 theme: function() { 184 $('#' + this.id).controlgroup(); 185 }, 186 187 /** 188 * This method is called everytime a item is selected / clicked. If the selected item 189 * changed, the defined onSelect action is triggered. 190 * 191 * @param {String} id The id of the selected item. 192 */ 193 itemSelected: function(id) { 194 var item = M.ViewManager.getViewById(id); 195 196 if(this.selectionMode === M.SINGLE_SELECTION) { 197 if(!_.isEqual(item, this.selection)) { 198 this.selection = item; 199 if(this.onSelect && this.onSelect.target && this.onSelect.action) { 200 this.onSelect.target[this.onSelect.action](); 201 } 202 } 203 } else { 204 if(!this.selection) { 205 this.selection = []; 206 } 207 208 if($('#' + id + ':checked').length > 0) { 209 this.selection.push(item); 210 } else { 211 this.selection = _.select(this.selection, function(i) { 212 return i !== item; 213 }); 214 } 215 216 if(this.onSelect && this.onSelect.target && this.onSelect.action) { 217 this.onSelect.target[this.onSelect.action](); 218 } 219 } 220 }, 221 222 /** 223 * This method returns the selected item's value(s) either as a String (M.SINGLE_SELECTION) 224 * or as an Array (M.MULTIPLE_SELECTION). 225 * 226 * @returns {String, Array} The selected item's value(s). 227 */ 228 getSelection: function() { 229 if(this.selectionMode === M.SINGLE_SELECTION) { 230 if(this.selection) { 231 return this.selection.value; 232 } 233 } else { 234 if(this.selection) { 235 var selection = []; 236 _.each(this.selection, function(item) { 237 selection.push(item.value); 238 }); 239 return selection; 240 } 241 } 242 }, 243 244 /** 245 * This method can be used to select items programmatically. The given parameter can either 246 * be a String (M.SINGLE_SELECTION) or an Array (M.MULTIPLE_SELECTION). 247 * 248 * @param {String, Array} selection The selection that should be applied to the selection list. 249 */ 250 setSelection: function(selection) { 251 this.removeSelection(); 252 var that = this; 253 if(this.selectionMode === M.SINGLE_SELECTION && typeof(selection) === 'string') { 254 $('#' + this.id).find('input').each(function() { 255 var item = M.ViewManager.getViewById($(this).attr('id')); 256 if(item.value === selection) { 257 item.isSelected = YES; 258 that.selection = item; 259 $(this).attr('checked', 'checked'); 260 $(this).siblings('label:first').addClass('ui-btn-active'); 261 $(this).siblings('label:first').find('span .ui-icon-radio-off').addClass('ui-icon-radio-on'); 262 $(this).siblings('label:first').find('span .ui-icon-radio-off').removeClass('ui-icon-radio-off'); 263 } 264 }); 265 } else if(typeof(selection) === 'object') { 266 $('#' + this.id).find('input').each(function() { 267 var item = M.ViewManager.getViewById($(this).attr('id')); 268 for(var i in selection) { 269 var selectionItem = selection[i]; 270 if(item.value === selectionItem) { 271 item.isSelected = YES; 272 that.selection.push(item); 273 $(this).attr('checked', 'checked'); 274 $(this).siblings('label:first').addClass('ui-btn-active'); 275 $(this).siblings('label:first').find('span .ui-icon-checkbox-off').addClass('ui-icon-checkbox-on'); 276 $(this).siblings('label:first').find('span .ui-icon-checkbox-off').removeClass('ui-icon-checkbox-off'); 277 } 278 } 279 }); 280 } 281 that.theme(); 282 }, 283 284 /** 285 * This method de-selects all of the selection list's items. 286 */ 287 removeSelection: function() { 288 var that = this; 289 var type = ''; 290 if(this.selectionMode === M.SINGLE_SELECTION) { 291 this.selection = null; 292 type = 'radio'; 293 } else { 294 this.selection = []; 295 type = 'checkbox'; 296 } 297 $('#' + this.id).find('input').each(function() { 298 var item = M.ViewManager.getViewById($(this).attr('id')); 299 item.isSelected = NO; 300 $(this).removeAttr('checked'); 301 $(this).siblings('label:first').removeClass('ui-btn-active'); 302 $(this).siblings('label:first').find('span .ui-icon-radio-on').addClass('ui-icon-' + type + '-off'); 303 $(this).siblings('label:first').find('span .ui-icon-radio-on').removeClass('ui-icon-' + type + '-on'); 304 }); 305 } 306 307 });