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 };