1/** 2 * This jQuery plugin displays pagination links inside the selected elements. 3 * 4 * This plugin needs at least jQuery 1.4.2 5 * 6 * @author Gabriel Birke (birke *at* d-scribe *dot* de) 7 * @version 2.0rc 8 * @param {int} maxentries Number of entries to paginate 9 * @param {Object} opts Several options (see README for documentation) 10 * @return {Object} jQuery Object 11 */ 12 (function($){ 13 /** 14 * @class Class for calculating pagination values 15 */ 16 $.PaginationCalculator = function(maxentries, opts) { 17 this.maxentries = maxentries; 18 this.opts = opts; 19 } 20 21 $.extend($.PaginationCalculator.prototype, { 22 /** 23 * Calculate the maximum number of pages 24 * @method 25 * @returns {Number} 26 */ 27 numPages:function() { 28 return Math.ceil(this.maxentries/this.opts.items_per_page); 29 }, 30 /** 31 * Calculate start and end point of pagination links depending on 32 * current_page and num_display_entries. 33 * @returns {Array} 34 */ 35 getInterval:function(current_page) { 36 var ne_half = Math.ceil(this.opts.num_display_entries/2); 37 var np = this.numPages(); 38 var upper_limit = np - this.opts.num_display_entries; 39 var start = current_page > ne_half ? Math.max( Math.min(current_page - ne_half, upper_limit), 0 ) : 0; 40 var end = current_page > ne_half?Math.min(current_page+ne_half, np):Math.min(this.opts.num_display_entries, np); 41 return {start:start, end:end}; 42 } 43 }); 44 45 // Initialize jQuery object container for pagination renderers 46 $.PaginationRenderers = {} 47 48 /** 49 * @class Default renderer for rendering pagination links 50 */ 51 $.PaginationRenderers.defaultRenderer = function(maxentries, opts) { 52 this.maxentries = maxentries; 53 this.opts = opts; 54 this.pc = new $.PaginationCalculator(maxentries, opts); 55 } 56 $.extend($.PaginationRenderers.defaultRenderer.prototype, { 57 /** 58 * Helper function for generating a single link (or a span tag if it's the current page) 59 * @param {Number} page_id The page id for the new item 60 * @param {Number} current_page 61 * @param {Object} appendopts Options for the new item: text and classes 62 * @returns {jQuery} jQuery object containing the link 63 */ 64 createLink:function(page_id, current_page, appendopts){ 65 var lnk, np = this.pc.numPages(); 66 page_id = page_id<0?0:(page_id<np?page_id:np-1); // Normalize page id to sane value 67 appendopts = $.extend({text:page_id+1, classes:""}, appendopts||{}); 68 if(page_id == current_page){ 69 lnk = $("<span class='current'>" + appendopts.text + "</span>"); 70 } 71 else 72 { 73 lnk = $("<a>" + appendopts.text + "</a>") 74 .attr('href', this.opts.link_to.replace(/__id__/,page_id)); 75 } 76 if(appendopts.classes){ lnk.addClass(appendopts.classes); } 77 lnk.data('page_id', page_id); 78 return lnk; 79 }, 80 // Generate a range of numeric links 81 appendRange:function(container, current_page, start, end) { 82 var i; 83 for(i=start; i<end; i++) { 84 this.createLink(i, current_page).appendTo(container); 85 } 86 }, 87 getLinks:function(current_page, eventHandler) { 88 var begin, end, 89 interval = this.pc.getInterval(current_page), 90 np = this.pc.numPages(), 91 fragment = $("<div class='pagination'></div>"); 92 93 // Generate "Previous"-Link 94 if(this.opts.prev_text && (current_page > 0 || this.opts.prev_show_always)){ 95 fragment.append(this.createLink(current_page-1, current_page, {text:this.opts.prev_text, classes:"prev"})); 96 } 97 // Generate starting points 98 if (interval.start > 0 && this.opts.num_edge_entries > 0) 99 { 100 end = Math.min(this.opts.num_edge_entries, interval.start); 101 this.appendRange(fragment, current_page, 0, end); 102 if(this.opts.num_edge_entries < interval.start && this.opts.ellipse_text) 103 { 104 jQuery("<span>"+this.opts.ellipse_text+"</span>").appendTo(fragment); 105 } 106 } 107 // Generate interval links 108 this.appendRange(fragment, current_page, interval.start, interval.end); 109 // Generate ending points 110 if (interval.end < np && this.opts.num_edge_entries > 0) 111 { 112 if(np-this.opts.num_edge_entries > interval.end && this.opts.ellipse_text) 113 { 114 jQuery("<span>"+this.opts.ellipse_text+"</span>").appendTo(fragment); 115 }
116 begin = Math.max(np-this.opts.num_edge_entries, interval.end); 117 this.appendRange(fragment, current_page, begin, np); 118 119 } 120 // Generate "Next"-Link 121 if(this.opts.next_text && (current_page < np-1 || this.opts.next_show_always)){ 122 fragment.append(this.createLink(current_page+1, current_page, {text:this.opts.next_text, classes:"next"})); 123 } 124 $('a', fragment).click(eventHandler); 125 return fragment; 126 } 127 }); 128 129 // Extend jQuery 130 $.fn.pagination = function(maxentries, opts){ 131 132 // Initialize options with default values 133 opts = jQuery.extend({ 134 items_per_page:10, 135 num_display_entries:10, 136 current_page:0, 137 num_edge_entries:0, 138 link_to:"#", 139 prev_text:"Prev", 140 next_text:"Next", 141 ellipse_text:"...", 142 prev_show_always:true, 143 next_show_always:true, 144 renderer:"defaultRenderer", 145 callback:function(){return false;} 146 },opts||{}); 147 148 var containers = this, 149 renderer, links, current_page; 150 151 152 /** 153 * This is the event handling function for the pagination links. 154 * @param {int} page_id The new page number 155 */ 156 function pageSelected(evt){ 157 var links, current_page = $(evt.target).data('page_id'); 158 containers.data('current_page', current_page); 159 links = renderer.getLinks(current_page, pageSelected); 160 containers.empty(); 161 links.appendTo(containers); 162 var continuePropagation = opts.callback(current_page, containers); 163 if (!continuePropagation) { 164 if (evt.stopPropagation) { 165 evt.stopPropagation(); 166 } 167 else { 168 evt.cancelBubble = true; 169 } 170 } 171 return continuePropagation; 172 } 173 174 current_page = opts.current_page; 175 containers.data('current_page', current_page); 176 // Create a sane value for maxentries and items_per_page 177 maxentries = (!maxentries || maxentries < 0)?1:maxentries; 178 opts.items_per_page = (!opts.items_per_page || opts.items_per_page < 0)?1:opts.items_per_page; 179 180 if(!$.PaginationRenderers[opts.renderer]) 181 { 182 throw new ReferenceError("Pagination renderer '" + opts.renderer + "' was not found in jQuery.PaginationRenderers object."); 183 } 184 renderer = new $.PaginationRenderers[opts.renderer](maxentries, opts); 185 186 containers.each(function() { 187 // Attach control functions to the DOM element 188 this.selectPage = function(page_id){ pageSelected(page_id);} 189 this.prevPage = function(){ 190 var current_page = containers.data('current_page'); 191 if (current_page > 0) { 192 pageSelected(current_page - 1); 193 return true; 194 } 195 else { 196 return false; 197 } 198 } 199 this.nextPage = function(){ 200 var current_page = containers.data('current_page'); 201 if(current_page < numPages()-1) { 202 pageSelected(current_page+1); 203 return true; 204 } 205 else { 206 return false; 207 } 208 } 209 }); 210 // When all initialisation is done, draw the links 211 links = renderer.getLinks(current_page, pageSelected); 212 containers.empty(); 213 links.appendTo(containers); 214 // call callback function 215 opts.callback(current_page, containers); 216 217} 218 219})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.