1 /** 2 * @author Gillis Haasnoot <gillis.haasnoot@gmail.com> 3 * @package Banana.Controls 4 * @summary DataGridPagerFilter 5 */ 6 7 goog.provide('Banana.Controls.DataGridPagerFilter'); 8 9 goog.require('Banana.Controls.DataControls.ListControls.ListControl'); 10 11 /** @namespace Banana.Controls.DataGridPagerFilter */ 12 namespace('Banana.Controls').DataGridPagerFilter = Banana.Controls.ListControl.extend( 13 /** @lends Banana.Controls.DataGridPagerFilter.prototype */ 14 { 15 /** 16 * Create data grid pager filter 17 * @constructs 18 * @extends Banana.Controls.ListControl 19 */ 20 init : function() 21 { 22 this._super(); 23 24 this.addCssClass("BDataGridFilter"); 25 this.addCssClass('BDataGridPagerFilter') 26 27 this.dropDown = new Banana.Controls.DropDown().setVisible(false); 28 29 this.pagerLinks = new Banana.Controls.Panel().addCssClass('BDataGridPagerFilterButtonContainer'); 30 31 this.addControl(this.dropDown); 32 this.addControl(this.pagerLinks); 33 34 this.dropDown.bind('selectionChanged',this.getProxy(this.pagerDropDownChanged)); 35 36 this.bind('dataChanged',this.getProxy(function(){ 37 38 this.onSetData(); 39 40 this.dropDown.setData(this.getData()); 41 42 this.createDropDownDataSource(); 43 44 if (this.datasource !=null) 45 { 46 this.createPageLinks(); 47 } 48 49 //true to make sure we dont end up in endless loop 50 this.triggerEvent('filterDataChanged',true); 51 })); 52 53 this.bind('dataSourceChanged',this.getProxy(function(){ 54 55 if (this.data ==null) 56 { 57 this.data = 0; 58 } 59 60 if (this.data !=null) 61 { 62 this.createPageLinks(); 63 this.createDropDownDataSource(); 64 } 65 this.triggerEvent('filterDataSourceChanged'); 66 })); 67 68 this.bind('indexChanged', this.getProxy(function() 69 { 70 this.createDropDownDataSource(); 71 this.triggerEvent('filterDataChanged'); 72 })); 73 } 74 }); 75 76 /** 77 * @return {String} 78 */ 79 Banana.Controls.DataGridPagerFilter.prototype.getAllKey = function() 80 { 81 return null; 82 }; 83 84 /** 85 * sets the field where to filter on 86 * @param {String} f 87 * @return {this} 88 */ 89 Banana.Controls.DataGridPagerFilter.prototype.setFilterField = function(f) 90 { 91 this.filterField = f; 92 return this; 93 }; 94 95 /** 96 * @return {String} 97 */ 98 Banana.Controls.DataGridPagerFilter.prototype.getFilterField = function() 99 { 100 return this.filterField; 101 }; 102 103 Banana.Controls.DataGridPagerFilter.prototype.nextClick = function() 104 { 105 if (this.getDataSource() <= (parseInt(this.getData())+1)) return; 106 107 this.setData((parseInt(this.getData())+1)); 108 jQuery(this).trigger('indexChanged',this.getData()); 109 }; 110 111 Banana.Controls.DataGridPagerFilter.prototype.previousClick = function() 112 { 113 if (this.getData() <= 0) return; 114 115 this.setData((parseInt(this.getData())-1)); 116 jQuery(this).trigger('indexChanged',this.getData()); 117 }; 118 119 Banana.Controls.DataGridPagerFilter.prototype.pagerDropDownChanged = function() 120 { 121 this.setData(parseInt(this.dropDown.getData())); 122 jQuery(this).trigger('indexChanged',this.dropDown.getData()); 123 this.createPageLinks(); 124 }; 125 126 /** 127 * @ignore 128 * @param owner of this pager 129 */ 130 Banana.Controls.DataGridPagerFilter.prototype.setDataGridOwner = function(datagrid) 131 { 132 this.datagridowner = datagrid; 133 }; 134 135 /** 136 * invoked after setting data on control. 137 * @ignore 138 */ 139 Banana.Controls.DataGridPagerFilter.prototype.onSetData = function(d) 140 { 141 142 }; 143 144 /** 145 * Creates pager links 146 */ 147 Banana.Controls.DataGridPagerFilter.prototype.createPageLinks = function() 148 { 149 this.pagerLinks.clear(); 150 151 if (this.datasource <= 1) 152 { 153 this.dropDown.setVisible(false); 154 return; 155 } 156 157 this.dropDown.setVisible(true); 158 159 var pages = parseInt(this.datasource); 160 var data = parseInt(this.data); 161 var startIndex = 1; 162 163 if (data > 2) 164 { 165 //we are reaching the end 166 if (pages - data < 3) 167 { 168 startIndex = pages - 4; 169 } 170 else 171 { 172 startIndex = data -1; 173 } 174 } 175 176 if (startIndex < 1) 177 { 178 startIndex = 1; 179 } 180 181 var endIndex = startIndex + 5; 182 183 if (endIndex > pages) 184 { 185 endIndex = pages+1; 186 } 187 188 // var start = new Banana.Controls.Button().addCssClass('BDataGridPagerButton').setLabelCssClass('BDataGridPagerButtonLabel'); 189 // start.setText('<< '); 190 191 var prev = new Banana.Controls.Button().addCssClass('BDataGridPagerFilterButton'); 192 prev.setText('< '); 193 194 //this.pagerLinks.addControl(start); 195 this.pagerLinks.addControl(prev); 196 197 for (i = startIndex; i < endIndex; i++) 198 { 199 if (i > this.datasource) {break;} 200 201 var b = new Banana.Controls.Button().addCssClass('BDataGridPagerFilterButton'); 202 b.setText(i); 203 if (i-1 == data) 204 { 205 b.addCssClass('BDataGridPagerFilterButtonSelected'); 206 } 207 this.pagerLinks.addControl(b); 208 209 b.bind('click',this.getProxy(this.onPageNavigate),i); 210 } 211 212 var next = new Banana.Controls.Button().addCssClass('BDataGridPagerFilterButton'); 213 next.setText('>'); 214 215 // var end = new Banana.Controls.Button().addCssClass('BDataGridPagerButton').setLabelCssClass('BDataGridPagerButtonLabel');; 216 // end.setText('>>'); 217 218 next.bind('click',this.getProxy(this.nextClick)); 219 220 prev.bind('click',this.getProxy(this.previousClick)); 221 222 this.pagerLinks.addControl(next); 223 //this.pagerLinks.addControl(end); 224 225 this.pagerLinks.invalidateDisplay(); 226 227 }; 228 229 Banana.Controls.DataGridPagerFilter.prototype.onPageNavigate = function(e) 230 { 231 this.setData((parseInt(e.data)-1)); 232 this.dropDown.setData((parseInt(e.data)-1)); 233 jQuery(this).trigger('indexChanged',this.getData()); 234 }; 235 236 237 /** 238 * creates datasource content (ported from phpmyadmin pager) 239 */ 240 Banana.Controls.DataGridPagerFilter.prototype.createDropDownDataSource = function() 241 { 242 //only proceed when we have data and datasource 243 if (!this.getDataSource()) 244 { 245 return; 246 } 247 var pages = parseInt(this.datasource); 248 249 //Start function with fixed data about the construction of the pager 250 var pageNow = parseInt(this.data); //current page number 251 var nbTotalPage = pages; //number of total pages 252 var showAll = 50; //If the number of pages is lower than this variable, no pages will be omitted in pagination 253 var sliceStart = 5; //How many rows at the beginning should always be shown? 254 var sliceEnd = 5; //How many rows at the end should always be shown? 255 var percent = 20; //Percentage of calculation page offsets to hop to a next page 256 var range = 10; // Near the current page, how many pages should be considered "nearby" and displayed as well? 257 var prompt = ''; //The prompt to display (sometimes empty) 258 259 var increment = Math.floor( nbTotalPage / percent); 260 var pageNowMinusRange = ( pageNow - range); 261 var pageNowPlusRange = ( pageNow + range); 262 263 var pages = []; 264 265 if (nbTotalPage < showAll) 266 { 267 //If the total page are less than how many page i have to show...i create an array with every pages 268 for (i = 1; i <= nbTotalPage; i++) 269 { 270 pages.push(i); 271 } 272 } 273 else 274 { 275 // Always show first X pages 276 var i; 277 for (i = 1; i <= sliceStart; i++) 278 { 279 pages.push(i); 280 } 281 282 // Always show last X pages 283 var j; 284 for (j = nbTotalPage - sliceEnd; j <= nbTotalPage; j++) 285 { 286 pages.push(j); 287 } 288 289 // Based on the number of results we add the specified 290 // $percent percentage to each page number, 291 // so that we have a representing page number every now and then to 292 // immediately jump to specific pages. 293 // As soon as we get near our currently chosen page ($pageNow - 294 // $range), every page number will be shown. 295 var k = sliceStart; 296 var x = nbTotalPage - sliceEnd; 297 var met_boundary = false; 298 while (k <= x) 299 { 300 if (k >= pageNowMinusRange && k <= pageNowPlusRange) 301 { 302 // If our pageselector comes near the current page, we use 1 303 // counter increments 304 k++; 305 met_boundary = true; 306 } 307 else 308 { 309 // We add the percentage increment to our current page to 310 // hop to the next one in range 311 k += increment; 312 313 // Make sure that we do not cross our boundaries. 314 if (k > pageNowMinusRange && ! met_boundary) 315 { 316 k = pageNowMinusRange; 317 } 318 } 319 320 if (k > 0 && k <= x) 321 { 322 pages.push(k); 323 } 324 } 325 326 /** 327 * @ignore 328 */ 329 sortfunc = function(a,b) 330 { 331 return parseInt(a,10) - parseInt(b,10); 332 }; 333 //sort the array 334 pages.sort(sortfunc); 335 } 336 337 var ds = new Array(); 338 for (var i in pages) 339 { 340 if (typeof (pages[i]) == 'function') 341 { 342 continue; 343 } 344 345 var ob = {}; 346 ob.key = pages[i]-1; 347 ob.value = pages[i]; 348 ds.push(ob); 349 } 350 this.dropDown.setDataSource(ds,true); 351 };