Dateigrösse: 22.96 kb
1 /* 2 paginate table object v1.6 by frequency-decoder.com 3 4 Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/) 5 6 Please credit frequency decoder in any derivative work - thanks 7 8 You are free: 9 10 * to copy, distribute, display, and perform the work 11 * to make derivative works 12 * to make commercial use of the work 13 14 Under the following conditions: 15 16 by Attribution. 17 -------------- 18 You must attribute the work in the manner specified by the author or licensor. 19 20 sa 21 -- 22 Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one. 23 24 * For any reuse or distribution, you must make clear to others the license terms of this work. 25 * Any of these conditions can be waived if you get permission from the copyright holder. 26 */ 27 tablePaginater = { 28 tableInfo: {}, 29 uniqueID:0, 30 /* 31 32 Localise the button titles here... 33 34 %p is replaced with the appropriate page number 35 %t is replaced with the total number of pages 36 37 */ 38 text: ["First Page","Previous Page (Page %p)","Next Page (Page %p)","Last Page (Page %t)","Page %p of %t"], 39 40 addEvent: function(obj, type, fn, tmp) { 41 tmp || (tmp = true); 42 if( obj.attachEvent ) { 43 obj["e"+type+fn] = fn; 44 obj[type+fn] = function(){obj["e"+type+fn]( window.event );}; 45 obj.attachEvent( "on"+type, obj[type+fn] ); 46 } else { 47 obj.addEventListener( type, fn, true ); 48 }; 49 }, 50 51 addClass: function(e,c) { 52 if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) return; 53 e.className += ( e.className ? " " : "" ) + c; 54 }, 55 56 /*@cc_on 57 /*@if (@_win32) 58 removeClass: function(e,c) { 59 e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1'); 60 }, 61 @else @*/ 62 removeClass: function(e,c) { 63 e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, ''); 64 }, 65 /*@end 66 @*/ 67 68 init: function(tableId) { 69 var tables = tableId && typeof(tableId) == "string" ? [document.getElementById(tableId)] : document.getElementsByTagName('table'); 70 var hook, maxPages, visibleRows, numPages, cp, cb, rowList; 71 72 for(var t = 0, tbl; tbl = tables[t]; t++) { 73 if(tbl.className.search(/paginate-([0-9]+)/) == -1) { continue; }; 74 75 if(!tbl.id) { tbl.id = "fdUniqueTableId_" + tablePaginater.uniqueID++; }; 76 77 maxPages = tbl.className.search(/max-pages-([0-9]+)/) == -1 ? null : Number(tbl.className.match(/max-pages-([0-9]+)/)[1]); 78 if(maxPages % 2 == 0 && maxPages > 1) { maxPages--; }; 79 80 hook = tbl.getElementsByTagName('tbody'); 81 hook = (hook.length) ? hook[0] : tbl; 82 83 visibleRows = tablePaginater.calculateVisibleRows(hook); 84 85 if(maxPages > (visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1]))) { 86 maxPages = null; 87 }; 88 89 numPages = Math.ceil(visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1])); 90 91 if(numPages < 2 && !(tbl.id in tablePaginater.tableInfo)) { 92 continue; 93 }; 94 95 cp = (tbl.id in tablePaginater.tableInfo) ? Math.min(tablePaginater.tableInfo[tbl.id].currentPage, numPages) : 1; 96 97 cb = tbl.className.search(/paginationcallback-([\S-]+)/) == -1 ? "" : tbl.className.match(/paginationcallback-([\S]+)/)[1]; 98 99 // Replace "-" with "." to enable Object.method callbacks 100 cb = cb.replace("-", "."); 101 102 tablePaginater.tableInfo[tbl.id] = { 103 rowsPerPage:Number(tbl.className.match(/paginate-([0-9]+)/)[1]), 104 currentPage:cp, 105 totalRows:hook.getElementsByTagName('tr').length, 106 hook:hook, 107 maxPages:maxPages, 108 numPages:numPages, 109 rowStyle:tbl.className.search(/rowstyle-([\S]+)/) != -1 ? tbl.className.match(/rowstyle-([\S]+)/)[1] : false, 110 callback:cb || "paginationCallback" 111 }; 112 113 tablePaginater.showPage(tbl.id); 114 hook = null; 115 }; 116 }, 117 calculateVisibleRows: function(hook) { 118 var trs = hook.rows; 119 var cnt = 0; 120 var reg = /(^|\s)invisibleRow(\s|$)/; 121 122 for(var i = 0, tr; tr = trs[i]; i++) { 123 if(tr.parentNode != hook || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue; 124 125 if(tr.className.search(reg) == -1) { 126 cnt++; 127 }; 128 }; 129 return cnt; 130 }, 131 createButton: function(details, ul, pseudo) { 132 var li = document.createElement("li"); 133 var but = document.createElement(pseudo ? "div" : "a"); 134 var span = document.createElement("span"); 135 136 if(!pseudo) { but.href = "#"; }; 137 if(!pseudo) { but.title = details.title; }; 138 139 but.className = details.className; 140 141 ul.appendChild(li); 142 li.appendChild(but); 143 but.appendChild(span); 144 span.appendChild(document.createTextNode(details.text)); 145 146 if(!pseudo) { li.onclick = but.onclick = tablePaginater.buttonClick; }; 147 if(!pseudo && details.id) { but.id = details.id; }; 148 149 li = but = span = null; 150 }, 151 removePagination: function(tableId) { 152 var wrapT = document.getElementById(tableId + "-fdtablePaginaterWrapTop"); 153 var wrapB = document.getElementById(tableId + "-fdtablePaginaterWrapBottom"); 154 if(wrapT) { wrapT.parentNode.removeChild(wrapT); }; 155 if(wrapB) { wrapB.parentNode.removeChild(wrapB); }; 156 }, 157 buildPagination: function(tblId) { 158 if(!(tblId in tablePaginater.tableInfo)) { return; }; 159 160 tablePaginater.removePagination(tblId); 161 162 var details = tablePaginater.tableInfo[tblId]; 163 164 if(details.numPages < 2) return; 165 166 function resolveText(txt, curr) { 167 curr = curr || details.currentPage; 168 return txt.replace("%p", curr).replace("%t", details.numPages); 169 }; 170 171 if(details.maxPages) { 172 findex = Math.max(0, Math.floor(Number(details.currentPage - 1) - (Number(details.maxPages - 1) / 2))); 173 lindex = findex + Number(details.maxPages); 174 if(lindex > details.numPages) { 175 lindex = details.numPages; 176 findex = Math.max(0, details.numPages - Number(details.maxPages)); 177 }; 178 } else { 179 findex = 0; 180 lindex = details.numPages; 181 }; 182 183 184 var wrapT = document.createElement("div"); 185 wrapT.className = "fdtablePaginaterWrap"; 186 wrapT.id = tblId + "-fdtablePaginaterWrapTop"; 187 188 var wrapB = document.createElement("div"); 189 wrapB.className = "fdtablePaginaterWrap"; 190 wrapB.id = tblId + "-fdtablePaginaterWrapBottom"; 191 192 // Create list scaffold 193 var ulT = document.createElement("ul"); 194 ulT.id = tblId + "-tablePaginater"; 195 196 var ulB = document.createElement("ul"); 197 ulB.id = tblId + "-tablePaginaterClone"; 198 ulT.className = ulB.className = "fdtablePaginater"; 199 200 // Add to the wrapper DIVs 201 wrapT.appendChild(ulT); 202 wrapB.appendChild(ulB); 203 204 // FIRST (only created if maxPages set) 205 if(details.maxPages) { 206 tablePaginater.createButton({title:tablePaginater.text[0], className:"first-page", text:"\u00ab"}, ulT, !findex); 207 tablePaginater.createButton({title:tablePaginater.text[0], className:"first-page", text:"\u00ab"}, ulB, !findex); 208 }; 209 210 // PREVIOUS (only created if there are more than two pages) 211 if(details.numPages > 2) { 212 tablePaginater.createButton({title:resolveText(tablePaginater.text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPage"}, ulT, details.currentPage == 1); 213 tablePaginater.createButton({title:resolveText(tablePaginater.text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPageC"}, ulB, details.currentPage == 1); 214 }; 215 216 // NUMBERED 217 for(var i = findex; i < lindex; i++) { 218 tablePaginater.createButton({title:resolveText(tablePaginater.text[4], i+1), className:i != (details.currentPage-1) ? "page-"+(i+1) : "currentPage page-"+(i+1), text:(i+1), id:i == (details.currentPage-1) ? tblId + "-currentPage" : ""}, ulT); 219 tablePaginater.createButton({title:resolveText(tablePaginater.text[4], i+1), className:i != (details.currentPage-1) ? "page-"+(i+1) : "currentPage page-"+(i+1), text:(i+1), id:i == (details.currentPage-1) ? tblId + "-currentPageC" : ""}, ulB); 220 }; 221 222 // NEXT (only created if there are more than two pages) 223 if(details.numPages > 2) { 224 tablePaginater.createButton({title:resolveText(tablePaginater.text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPage"}, ulT, details.currentPage == details.numPages); 225 tablePaginater.createButton({title:resolveText(tablePaginater.text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPageC"}, ulB, details.currentPage == details.numPages); 226 }; 227 228 // LAST (only created if maxPages set) 229 if(details.maxPages) { 230 tablePaginater.createButton({title:resolveText(tablePaginater.text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulT, lindex == details.numPages); 231 tablePaginater.createButton({title:resolveText(tablePaginater.text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulB, lindex == details.numPages); 232 }; 233 234 // DOM inject wrapper DIVs (FireFox Bug: this has to be done here if you use display:table) 235 if(document.getElementById(tblId+"-paginationListWrapTop")) { 236 document.getElementById(tblId+"-paginationListWrapTop").appendChild(wrapT); 237 } else { 238 document.getElementById(tblId).parentNode.insertBefore(wrapT, document.getElementById(tblId)); 239 }; 240 241 if(document.getElementById(tblId+"-paginationListWrapBottom")) { 242 document.getElementById(tblId+"-paginationListWrapBottom").appendChild(wrapB); 243 } else { 244 document.getElementById(tblId).parentNode.insertBefore(wrapB, document.getElementById(tblId).nextSibling); 245 }; 246 }, 247 // The tableSort script uses this function to redraw. 248 redraw: function(tableid, identical) { 249 if(!tableid || !(tableid in fdTableSort.tableCache) || !(tableid in tablePaginater.tableInfo)) { return; }; 250 251 var dataObj = fdTableSort.tableCache[tableid]; 252 var data = dataObj.data; 253 var len1 = data.length; 254 var len2 = len1 ? data[0].length - 1 : 0; 255 var hook = dataObj.hook; 256 var colStyle = dataObj.colStyle; 257 var rowStyle = dataObj.rowStyle; 258 var colOrder = dataObj.colOrder; 259 260 var page = tablePaginater.tableInfo[tableid].currentPage - 1; 261 var d1 = tablePaginater.tableInfo[tableid].rowsPerPage * page; 262 var d2 = Math.min(tablePaginater.tableInfo[tableid].totalRows, d1 + tablePaginater.tableInfo[tableid].rowsPerPage); 263 264 var cnt = 0; 265 var rs = 0; 266 var reg = /(^|\s)invisibleRow(\s|$)/; 267 268 var tr, tds, cell, pos; 269 270 for(var i = 0; i < len1; i++) { 271 tr = data[i][len2]; 272 273 if(colStyle) { 274 tds = tr.cells; 275 for(thPos in colOrder) { 276 if(!colOrder[thPos]) tablePaginater.removeClass(tds[thPos], colStyle); 277 else tablePaginater.addClass(tds[thPos], colStyle); 278 }; 279 }; 280 281 if(tr.className.search(reg) != -1) { 282 continue; 283 }; 284 285 if(!identical) { 286 cnt++; 287 288 if(cnt > d1 && cnt <= d2) { 289 if(rowStyle) { 290 if(rs++ & 1) tablePaginater.addClass(tr, rowStyle); 291 else tablePaginater.removeClass(tr, rowStyle); 292 }; 293 tr.style.display = ""; 294 } else { 295 tr.style.display = "none"; 296 }; 297 298 // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser 299 // hook.removeChild(tr); 300 hook.appendChild(tr); 301 }; 302 }; 303 304 tr = tds = hook = null; 305 }, 306 showPage: function(tblId, pageNum) { 307 if(!(tblId in tablePaginater.tableInfo)) { return; }; 308 309 var page = !pageNum ? tablePaginater.tableInfo[tblId].currentPage - 1 : pageNum - 1; 310 311 var d1 = tablePaginater.tableInfo[tblId].rowsPerPage * page; 312 var d2 = Math.min(tablePaginater.tableInfo[tblId].totalRows, d1 + tablePaginater.tableInfo[tblId].rowsPerPage); 313 var trs = tablePaginater.tableInfo[tblId].hook.rows; 314 var cnt = 0; 315 var rc = 0; 316 var len = trs.length; 317 var rs = tablePaginater.tableInfo[tblId].rowStyle; 318 var reg = /(^|\s)invisibleRow(\s|$)/; 319 320 for(var i = 0; i < len; i++) { 321 if(trs[i].getElementsByTagName("th").length || (trs[i].parentNode && trs[i].parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue; 322 323 if(trs[i].className.search(reg) != -1) { 324 continue; 325 }; 326 327 cnt++; 328 329 if(cnt > d1 && cnt <= d2) { 330 if(rs) { 331 if(rc++ & 1) { 332 tablePaginater.addClass(trs[i], rs); 333 } else { 334 tablePaginater.removeClass(trs[i], rs); 335 } 336 }; 337 trs[i].style.display = ""; 338 } else { 339 trs[i].style.display = "none"; 340 }; 341 }; 342 343 tablePaginater.buildPagination(tblId); 344 tablePaginater.callback(tblId); 345 }, 346 callback: function(tblId) { 347 var func; 348 if(tablePaginater.tableInfo[tblId].callback.indexOf(".") != -1) { 349 var split = tablePaginater.tableInfo[tblId].callback.split("."); 350 func = window; 351 for(var i = 0, f; f = split[i]; i++) { 352 if(f in func) { 353 func = func[f]; 354 } else { 355 func = ""; 356 break; 357 }; 358 }; 359 } else if(tablePaginater.tableInfo[tblId].callback in window) { 360 func = window[tablePaginater.tableInfo[tblId].callback]; 361 }; 362 363 if(typeof func == "function") { 364 func(tblId); 365 }; 366 367 func = null; 368 }, 369 buttonClick: function(e) { 370 e = e || window.event; 371 372 var a = this.tagName.toLowerCase() == "a" ? this : this.getElementsByTagName("a")[0]; 373 374 if(a.className.search("currentPage") != -1) return false; 375 376 var ul = this; 377 while(ul.tagName.toLowerCase() != "ul") ul = ul.parentNode; 378 379 var tblId = ul.id.replace("-tablePaginaterClone","").replace("-tablePaginater", ""); 380 381 tablePaginater.tableInfo[tblId].lastPage = tablePaginater.tableInfo[tblId].currentPage; 382 383 var showPrevNext = 0; 384 385 if(a.className.search("previous-page") != -1) { 386 tablePaginater.tableInfo[tblId].currentPage = tablePaginater.tableInfo[tblId].currentPage > 1 ? tablePaginater.tableInfo[tblId].currentPage - 1 : tablePaginater.tableInfo[tblId].numPages; 387 showPrevNext = 1; 388 } else if(a.className.search("next-page") != -1) { 389 tablePaginater.tableInfo[tblId].currentPage = tablePaginater.tableInfo[tblId].currentPage < tablePaginater.tableInfo[tblId].numPages ? tablePaginater.tableInfo[tblId].currentPage + 1 : 1; 390 showPrevNext = 2; 391 } else if(a.className.search("first-page") != -1) { 392 tablePaginater.tableInfo[tblId].currentPage = 1; 393 } else if(a.className.search("last-page") != -1) { 394 tablePaginater.tableInfo[tblId].currentPage = tablePaginater.tableInfo[tblId].numPages; 395 } else { 396 tablePaginater.tableInfo[tblId].currentPage = parseInt(a.className.match(/page-([0-9]+)/)[1]) || 1; 397 }; 398 399 tablePaginater.showPage(tblId); 400 401 // Focus on the appropriate button (previous, next or the current page) 402 // I'm hoping screen readers are savvy enough to indicate the focus event to the user 403 if(showPrevNext == 1) { 404 var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-previousPageC" : tblId + "-previousPage"); 405 } else if(showPrevNext == 2) { 406 var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-nextPageC" : tblId + "-nextPage"); 407 } else { 408 var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-currentPageC" : tblId + "-currentPage"); 409 }; 410 411 if(elem && elem.tagName.toLowerCase() == "a") { elem.focus(); }; 412 413 if(e.stopPropagation) { 414 e.stopPropagation(); 415 e.preventDefault(); 416 }; 417 418 /*@cc_on 419 @if(@_win32) 420 e.cancelBubble = true; 421 e.returnValue = false; 422 @end 423 @*/ 424 return false; 425 }, 426 onUnLoad: function(e) { 427 var tbl, lis, pagination, uls; 428 for(tblId in tablePaginater.tableInfo) { 429 uls = [tblId + "-tablePaginater", tblId + "-tablePaginaterClone"]; 430 for(var z = 0; z < 2; z++) { 431 pagination = document.getElementById(uls[z]); 432 if(!pagination) { continue; }; 433 lis = pagination.getElementsByTagName("li"); 434 for(var i = 0, li; li = lis[i]; i++) { 435 li.onclick = null; 436 if(li.getElementsByTagName("a").length) { li.getElementsByTagName("a")[0].onclick = null; }; 437 }; 438 }; 439 }; 440 } 441 }; 442 443 tablePaginater.addEvent(window, "load", tablePaginater.init); 444 tablePaginater.addEvent(window, "unload", tablePaginater.onUnLoad); 445