1 /** 2 * @author Gillis Haasnoot <gillis.haasnoot@gmail.com> 3 * @package Banana.Controls 4 * @summary Datagrid 5 */ 6 7 goog.provide('Banana.Controls.DataGrid'); 8 9 goog.require('Banana.Controls.DataGridTableListRender'); 10 goog.require('Banana.Controls.DataGridTileListRender'); 11 goog.require('Banana.Controls.DataGridTreeListRender'); 12 goog.require('Banana.Controls.DataGridDataTreeListRender'); 13 goog.require('Banana.Controls.DataGridControlPanel'); 14 15 goog.require('Banana.Controls.DataGridCheckboxFilter'); 16 goog.require('Banana.Controls.DataGridDropDownFilter'); 17 goog.require('Banana.Controls.DataGridSearchFilter'); 18 goog.require('Banana.Controls.DataGridPagerFilter'); 19 goog.require('Banana.Controls.DataGridDateFilter'); 20 21 /** @namespace Banana.Controls.DataGrid */ 22 namespace('Banana.Controls').DataGrid = Banana.Controls.ListControl.extend( 23 /** @lends Banana.Controls.DataGrid.prototype */ 24 { 25 /** 26 * Creates a datagrid 27 * A datagrid is a more advanced list control with functionality to have its own listrender. 28 * A listrender is responsible for rendering the list and is completely independent from the datagrid itself. 29 * By default a datagrid is having a table list render . 30 * A different listrender can replace the current listrender if desired at anytime. 31 * Empty template can be assigned to a datagrid which is shown when there is no data inside the 32 * datagrid. 33 * 34 Example: 35 36 var datagrid = new Banana.Controls.DataGrid(); 37 38 var columns = [ 39 new Banana.Controls.DataGridColumn().setHeaderText('name').setDataField('name'), 40 new Banana.Controls.DataGridColumn().setHeaderText('description').setDataField('description') 41 ]; 42 43 datagrid.getListRender().setColumns(colums); 44 45 var datasource = [ 46 {'name':'a name1','description':'a description1'}, 47 {'name':'a name2','description':'a description2'}, 48 {'name':'a name3','description':'a description3'} 49 ]; 50 51 datagrid.setDataSource(datasource); 52 53 this.addControl(datagrid); 54 55 * 56 * @constructs 57 * @extends Banana.Controls.ListControl 58 */ 59 init : function() 60 { 61 this._super(); 62 63 this.addCssClass('BDataGrid'); 64 65 this.datasource = []; 66 67 this.listRender = null; 68 this.listRenderCreated = false; 69 70 this.createBasicControls(); 71 }, 72 73 /** 74 * Internaly used 75 * @ignore 76 */ 77 createComponents : function() 78 { 79 this.triggerEvent('datagridReady'); 80 }, 81 82 /** 83 * @ignore 84 */ 85 updateDisplay : function() 86 { 87 if (!this.listRenderCreated) 88 { 89 this.createEmptyTemplate(); 90 } 91 }, 92 93 /** 94 * @param {mixed} datasource to fill the datagrid with 95 * @return {this} 96 */ 97 setDataSource : function(datasource) 98 { 99 this.datasource = datasource; 100 101 this.triggerEvent('onSetDataSource',datasource); 102 return this; 103 }, 104 105 /** 106 * setData method is equal to the setDataSource method. This method is used 107 * when datagrid is binded to data in a dataset. 108 * @param {mixed} data 109 * @return {this} 110 */ 111 setData : function(data) 112 { 113 this.setDataSource(data); 114 return this; 115 }, 116 117 /** 118 * equal to getDataSource 119 * @return {mixed} 120 */ 121 getData : function() 122 { 123 return this.datasource; 124 }, 125 126 /** 127 * add a control panal above the datagrid. 128 * A control panel is used as a container for filters and other controls interacting 129 * with the datagrid. 130 * 131 * @param {Banana.Controls.DataGridControlPanel} c 132 * @return {this} 133 */ 134 setControlPanel : function(c) 135 { 136 if (!(c instanceof(Banana.Controls.DataGridControlPanel))) 137 { 138 return this; 139 } 140 141 this.controlPanelHolder.addControl(c); 142 return this; 143 }, 144 145 /** 146 * @return {Banana.Controls.DataGridControlPanel} 147 */ 148 getControlPanel : function() 149 { 150 return this.controlPanelHolder.controls[0]; 151 }, 152 153 /** 154 * An empty template is shown when no datasource or empty datasource is inside the datagrid. 155 * @param {Banana.Controls.UiControl} c 156 * @return {this} 157 */ 158 setEmptyTemplate : function(c) 159 { 160 this.emptyTemplate = c; 161 162 this.clearEmptyTemplate(); 163 this.createEmptyTemplate(); 164 165 return this; 166 }, 167 168 /** 169 * Create building blocks which are needed to visualize our datagrid. 170 * From top to bottom we create a control panel holder, the list holder, info holder for the empty template 171 * and loader holder to show a loader. 172 * 173 * @ignore 174 */ 175 createBasicControls : function() 176 { 177 this.controlPanelHolder = new Banana.Control(); 178 this.listHolder = new Banana.Controls.Panel(); 179 this.infoHolder = new Banana.Controls.Panel().addCssClass('BDataGridInfoHolder'); 180 this.loaderHolder = new Banana.Controls.Panel(); 181 182 this.addControl(this.loaderHolder); 183 this.addControl(this.controlPanelHolder); 184 this.addControl(this.listHolder); 185 this.addControl(this.infoHolder); 186 }, 187 188 /** 189 * Sets the list render responsible for rendering content. 190 * If changed during runtime we rerender the complete datagrid. 191 * 192 * @param {Banana.Controls.Banana.Controls.DataGridBaseListRender} lr 193 * @return {this} 194 */ 195 setListRender : function(lr) 196 { 197 this.clearListRender(); 198 199 this.listRender = lr; 200 this.listRender.datagrid = this; 201 //force rerender if datasource is available 202 if (this.datasource && this.datasource.length) 203 { 204 this.setDataSource(this.datasource); 205 } 206 207 return this; 208 }, 209 210 /** 211 * returns current active list render. If none is active we return a default table list render 212 * @return {Banana.Controls.DataGridBaseListRender} listRender 213 */ 214 getListRender : function() 215 { 216 if (!this.listRender) 217 { 218 this.listRender = new Banana.Controls.DataGridTableListRender(); 219 } 220 221 return this.listRender; 222 }, 223 224 /** 225 * Clears the list render. 226 * @return {this} 227 */ 228 clearListRender : function() 229 { 230 this.listHolder.clear(); 231 return this; 232 }, 233 234 /** 235 * Create the listRender 236 * @ignore 237 */ 238 createListRender : function() 239 { 240 if (!this.listRender || !this.listRender.id) 241 { 242 this.listRender = this.getListRender(); 243 } 244 245 //if list holder is not already added to its placeholder 246 if (this.listHolder.controls.indexOf(this.listRender) === -1) 247 { 248 this.listHolder.addControl(this.listRender); 249 this.listRender.datagrid = this; 250 this.listRenderCreated = true; 251 252 //bind event. if source is 0 we create empty template, otherwise remove it 253 this.listRender.bind('dataSourceChanged',this.getProxy(function(e,f){ 254 255 this.datasource = this.listRender.datasource; //synchronize datasources 256 257 ///if already cleared and datasource is bigger than zero 258 if (this.emptyTemplateCleared && this.datasource.length) 259 { 260 return; 261 } 262 263 this.emptyTemplateCleared = false; 264 265 if (this.datasource.length) 266 { 267 this.clearEmptyTemplate(); 268 this.emptyTemplateCleared = true; 269 } 270 else 271 { 272 this.createEmptyTemplate(); 273 } 274 })); 275 } 276 }, 277 278 /** 279 * Invoked when datasource is set 280 * we start the creation of controls here 281 * @ignore 282 */ 283 onSetDataSource : function() 284 { 285 if (!this.datasource) 286 { 287 this.datasource = []; 288 } 289 //datasource needs to be a indexed array 290 if (!this.datasource.length) 291 { 292 this.createEmptyTemplate(); 293 } 294 else 295 { 296 this.infoHolder.setVisible(false); 297 } 298 299 if (this.listRender) 300 { 301 this.listRender.clear(); 302 } 303 304 this.createListRender(); 305 306 this.listRender.setDataSource(this.datasource); 307 308 if (this.isRendered) 309 { 310 this.listHolder.invalidateDisplay(); 311 } 312 }, 313 314 /** 315 * @abstract 316 * @ignore 317 */ 318 showInitLoader : function(){}, 319 320 /** 321 * @abstract 322 * @ignore 323 */ 324 renderList : function(){}, 325 326 /** 327 * @abstract 328 * @ignore 329 */ 330 showLoader : function(){}, 331 332 /** 333 * creates an empty template. 334 * 335 * @ignore 336 */ 337 createEmptyTemplate : function() 338 { 339 this.infoHolder.clear(); 340 341 if (this.emptyTemplate) 342 { 343 this.infoHolder.addControl(this.emptyTemplate(),true).setVisible(true); 344 } 345 else 346 { 347 this.infoHolder.addControl('No data found',true).setVisible(true); 348 } 349 }, 350 351 /** 352 * clears the empty template. 353 * @return {this} 354 */ 355 clearEmptyTemplate : function() 356 { 357 this.infoHolder.clear(); 358 return this; 359 } 360 });