X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=plekit%2Ftablesort%2Fpaginate.js;h=871c100fc130a8f022eb965d8a14e2c34a986345;hb=adfd75f0d83b047e2a3c1494cbbe0c492e10886c;hp=0dfcc7d003c4b2cdeca7b6934ac66e06feccba17;hpb=89b3b635298a23b0f62430cfb189882e248ab2fb;p=plewww.git diff --git a/plekit/tablesort/paginate.js b/plekit/tablesort/paginate.js index 0dfcc7d..871c100 100644 --- a/plekit/tablesort/paginate.js +++ b/plekit/tablesort/paginate.js @@ -1,479 +1,479 @@ -/* - paginate table object v2.0 by frequency-decoder.com - - Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/) - - Please credit frequency decoder in any derivative work - thanks - - You are free: - - * to copy, distribute, display, and perform the work - * to make derivative works - * to make commercial use of the work - - Under the following conditions: - - by Attribution. - -------------- - You must attribute the work in the manner specified by the author or licensor. - - sa - -- - 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. - - * For any reuse or distribution, you must make clear to others the license terms of this work. - * Any of these conditions can be waived if you get permission from the copyright holder. -*/ - -var tablePaginater = (function() { - /* - - Localise the button titles here... - - %p is replaced with the appropriate page number - %t is replaced with the total number of pages - - */ - var tableInfo = {}, - uniqueID = 0, - text = ["First Page","Previous Page (Page %p)","Next Page (Page %p)","Last Page (Page %t)","Page %p of %t"]; - - var addClass = function(e,c) { - if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) return; - e.className += ( e.className ? " " : "" ) + c; - }; - - /*@cc_on - /*@if (@_win32) - var removeClass = function(e,c) { - e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1'); - }; - @else @*/ - var removeClass = function(e,c) { - e.className = !c ? "" : (e.className || "").replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; - /*@end - @*/ - - var addEvent = function(obj, type, fn) { - if( obj.attachEvent ) { - obj["e"+type+fn] = fn; - obj[type+fn] = function(){obj["e"+type+fn]( window.event );}; - obj.attachEvent( "on"+type, obj[type+fn] ); - } else { - obj.addEventListener( type, fn, true ); - }; - }; - var removeEvent = function(obj, type, fn) { - try { - if( obj.detachEvent ) { - obj.detachEvent( "on"+type, obj[type+fn] ); - obj[type+fn] = null; - } else { - obj.removeEventListener( type, fn, true ); - }; - } catch(err) {}; - }; - var stopEvent = function(e) { - e = e || window.event; - if(e.stopPropagation) { - e.stopPropagation(); - e.preventDefault(); - }; - - /*@cc_on@*/ - /*@if(@_win32) - e.cancelBubble = true; - e.returnValue = false; - /*@end@*/ - return false; - }; - - var init = function(tableId) { - var tables = tableId && typeof(tableId) == "string" ? [document.getElementById(tableId)] : document.getElementsByTagName('table'), - hook, maxPages, visibleRows, numPages, cp, cb, rowList; - - for(var t = 0, tbl; tbl = tables[t]; t++) { - if(tbl.className.search(/paginate-([0-9]+)/) == -1) { continue; }; - - if(!tbl.id) { tbl.id = "fdUniqueTableId_" + uniqueID++; }; - - maxPages = tbl.className.search(/max-pages-([0-9]+)/) == -1 ? null : Number(tbl.className.match(/max-pages-([0-9]+)/)[1]); - if(maxPages % 2 == 0 && maxPages > 1) { maxPages--; }; - - hook = tbl.getElementsByTagName('tbody'); - hook = (hook.length) ? hook[0] : tbl; - - visibleRows = calculateVisibleRows(hook); - - if(maxPages > (visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1]))) { - maxPages = null; - }; - - numPages = Math.ceil(visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1])); - - if(numPages < 2 && !(tbl.id in tableInfo)) { - continue; - }; - - cp = (tbl.id in tableInfo) ? Math.min(tableInfo[tbl.id].currentPage, numPages) : 1; - - tableInfo[tbl.id] = { - rowsPerPage:Number(tbl.className.match(/paginate-([0-9]+)/)[1]), - currentPage:cp, - totalRows:hook.getElementsByTagName('tr').length, - hook:hook, - maxPages:maxPages, - numPages:numPages, - rowStyle:tbl.className.search(/rowstyle-([\S]+)/) != -1 ? tbl.className.match(/rowstyle-([\S]+)/)[1] : false, - callbacks:parseCallback(/^paginationcallback-/i, /paginationcallback-([\S-]+)/ig, tbl.className) - }; - - showPage(tbl.id); - hook = null; - }; - }; - - var parseCallback = function(head, regExp, cname) { - var cbs = [], - matchs = cname.match(regExp), - parts, obj, func; - - if(!matchs) { return []; }; - - for(var i = 0, mtch; mtch = matchs[i]; i++) { - mtch = mtch.replace(head, "").replace(/-/g, "."); - - try { - if(mtch.indexOf(".") != -1) { - parts = mtch.split('.'); - obj = window; - for (var x = 0, part; part = obj[parts[x]]; x++) { - if(part instanceof Function) { - (function() { - var method = part; - func = function (data) { method.apply(obj, [data]) }; - })(); - } else { - obj = part; - }; - }; - } else { - func = window[mtch]; - }; - - if(!(func instanceof Function)) continue; - cbs[cbs.length] = func; - } catch(err) {}; - }; - - return cbs; - }; - - var callback = function(tblId, opts) { - if(!(tblId in tableInfo) || !(tableInfo[tblId]["callbacks"].length)) return; - for(var i = 0, func; func = tableInfo[tblId]["callbacks"][i]; i++) { - func(opts || {}); - }; - }; - - var calculateVisibleRows = function(hook) { - var trs = hook.rows, - cnt = 0, - reg = /(^|\s)invisibleRow(\s|$)/; - - for(var i = 0, tr; tr = trs[i]; i++) { - if(tr.parentNode != hook || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue; - if(tr.className.search(reg) == -1) { cnt++; }; - }; - - return cnt; - }; - - var createButton = function(details, ul, pseudo) { - var li = document.createElement("li"), - but = document.createElement(pseudo ? "div" : "a"), - span = document.createElement("span"); - - if(!pseudo) { - but.href = "#"; - but.title = details.title; - }; - - but.className = details.className; - - ul.appendChild(li); - li.appendChild(but); - but.appendChild(span); - span.appendChild(document.createTextNode(details.text)); - - if(!pseudo) { - li.onclick = but.onclick = buttonClick; - if(details.id) { but.id = details.id; }; - }; - - li = but = span = null; - }; - var removePagination = function(tableId) { - var wrapT = document.getElementById(tableId + "-fdtablePaginaterWrapTop"), - wrapB = document.getElementById(tableId + "-fdtablePaginaterWrapBottom"); - if(wrapT) { wrapT.parentNode.removeChild(wrapT); }; - if(wrapB) { wrapB.parentNode.removeChild(wrapB); }; - }; - var buildPagination = function(tblId) { - if(!(tblId in tableInfo)) { return; }; - - removePagination(tblId); - - var details = tableInfo[tblId]; - - if(details.numPages < 2) return; - - function resolveText(txt, curr) { - curr = curr || details.currentPage; - return txt.replace("%p", curr).replace("%t", details.numPages); - }; - - if(details.maxPages) { - findex = Math.max(0, Math.floor(Number(details.currentPage - 1) - (Number(details.maxPages - 1) / 2))); - lindex = findex + Number(details.maxPages); - if(lindex > details.numPages) { - lindex = details.numPages; - findex = Math.max(0, details.numPages - Number(details.maxPages)); - }; - } else { - findex = 0; - lindex = details.numPages; - }; - - - var wrapT = document.createElement("div"); - wrapT.className = "fdtablePaginaterWrap"; - wrapT.id = tblId + "-fdtablePaginaterWrapTop"; - - var wrapB = document.createElement("div"); - wrapB.className = "fdtablePaginaterWrap"; - wrapB.id = tblId + "-fdtablePaginaterWrapBottom"; - - // Create list scaffold - var ulT = document.createElement("ul"); - ulT.id = tblId + "-tablePaginater"; - - var ulB = document.createElement("ul"); - ulB.id = tblId + "-tablePaginaterClone"; - ulT.className = ulB.className = "fdtablePaginater"; - - // Add to the wrapper DIVs - wrapT.appendChild(ulT); - wrapB.appendChild(ulB); - - // FIRST (only created if maxPages set) - if(details.maxPages) { - createButton({title:text[0], className:"first-page", text:"\u00ab"}, ulT, !findex); - createButton({title:text[0], className:"first-page", text:"\u00ab"}, ulB, !findex); - }; - - // PREVIOUS (only created if there are more than two pages) - if(details.numPages > 2) { - createButton({title:resolveText(text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPage"}, ulT, details.currentPage == 1); - createButton({title:resolveText(text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPageC"}, ulB, details.currentPage == 1); - }; - - // NUMBERED - for(var i = findex; i < lindex; i++) { - createButton({title:resolveText(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); - createButton({title:resolveText(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); - }; - - // NEXT (only created if there are more than two pages) - if(details.numPages > 2) { - createButton({title:resolveText(text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPage"}, ulT, details.currentPage == details.numPages); - createButton({title:resolveText(text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPageC"}, ulB, details.currentPage == details.numPages); - }; - - // LAST (only created if maxPages set) - if(details.maxPages) { - createButton({title:resolveText(text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulT, lindex == details.numPages); - createButton({title:resolveText(text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulB, lindex == details.numPages); - }; - - // DOM inject wrapper DIVs (FireFox 2.x Bug: this has to be done here if you use display:table) - if(document.getElementById(tblId+"-paginationListWrapTop")) { - document.getElementById(tblId+"-paginationListWrapTop").appendChild(wrapT); - } else { - document.getElementById(tblId).parentNode.insertBefore(wrapT, document.getElementById(tblId)); - }; - - if(document.getElementById(tblId+"-paginationListWrapBottom")) { - document.getElementById(tblId+"-paginationListWrapBottom").appendChild(wrapB); - } else { - document.getElementById(tblId).parentNode.insertBefore(wrapB, document.getElementById(tblId).nextSibling); - }; - }; - - // The tableSort script uses this function to redraw. - var tableSortRedraw = function(tableid, identical) { - if(!tableid || !(tableid in fdTableSort.tableCache) || !(tableid in tableInfo)) { return; }; - - var dataObj = fdTableSort.tableCache[tableid], - data = dataObj.data, - len1 = data.length, - len2 = len1 ? data[0].length - 1 : 0, - hook = dataObj.hook, - colStyle = dataObj.colStyle, - rowStyle = dataObj.rowStyle, - colOrder = dataObj.colOrder, - page = tableInfo[tableid].currentPage - 1, - d1 = tableInfo[tableid].rowsPerPage * page, - d2 = Math.min(tableInfo[tableid].totalRows, d1 + tableInfo[tableid].rowsPerPage), - cnt = 0, - rs = 0, - reg = /(^|\s)invisibleRow(\s|$)/, - tr, tds, cell, pos; - - for(var i = 0; i < len1; i++) { - tr = data[i][len2]; - - if(colStyle) { - tds = tr.cells; - for(thPos in colOrder) { - if(!colOrder[thPos]) removeClass(tds[thPos], colStyle); - else addClass(tds[thPos], colStyle); - }; - }; - - if(tr.className.search(reg) != -1) { continue; }; - - if(!identical) { - cnt++; - - if(cnt > d1 && cnt <= d2) { - if(rowStyle) { - if(rs++ & 1) addClass(tr, rowStyle); - else removeClass(tr, rowStyle); - }; - tr.style.display = ""; - } else { - tr.style.display = "none"; - }; - - // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser - // hook.removeChild(tr); - hook.appendChild(tr); - }; - }; - - tr = tds = hook = null; - }; - - var showPage = function(tblId, pageNum) { - if(!(tblId in tableInfo)) { return; }; - - var page = Math.max(0, !pageNum ? tableInfo[tblId].currentPage - 1 : pageNum - 1), - d1 = tableInfo[tblId].rowsPerPage * page, - d2 = Math.min(tableInfo[tblId].totalRows, d1 + tableInfo[tblId].rowsPerPage), - trs = tableInfo[tblId].hook.rows, - cnt = 0, - rc = 0, - len = trs.length, - rs = tableInfo[tblId].rowStyle, - reg = /(^|\s)invisibleRow(\s|$)/, - row = []; - - for(var i = 0; i < len; i++) { - if(trs[i].className.search(reg) != -1 || trs[i].getElementsByTagName("th").length || (trs[i].parentNode && trs[i].parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) { continue; }; - - cnt++; - - if(cnt > d1 && cnt <= d2) { - if(rs) { - if(rc++ & 1) { - addClass(trs[i], rs); - } else { - removeClass(trs[i], rs); - } - }; - trs[i].style.display = ""; - row[row.length] = trs[i]; - } else { - trs[i].style.display = "none"; - }; - }; - - buildPagination(tblId); - callback(tblId, {"totalRows":len, "currentPage":(page+1), "rowsPerPage":tableInfo[tblId].rowsPerPage, "visibleRows":row}); - }; - - var buttonClick = function(e) { - e = e || window.event; - - var a = this.tagName.toLowerCase() == "a" ? this : this.getElementsByTagName("a")[0]; - - if(a.className.search("currentPage") != -1) return false; - - var ul = this; - while(ul.tagName.toLowerCase() != "ul") ul = ul.parentNode; - - var tblId = ul.id.replace("-tablePaginaterClone","").replace("-tablePaginater", ""); - - tableInfo[tblId].lastPage = tableInfo[tblId].currentPage; - - var showPrevNext = 0; - - if(a.className.search("previous-page") != -1) { - tableInfo[tblId].currentPage = tableInfo[tblId].currentPage > 1 ? tableInfo[tblId].currentPage - 1 : tableInfo[tblId].numPages; - showPrevNext = 1; - } else if(a.className.search("next-page") != -1) { - tableInfo[tblId].currentPage = tableInfo[tblId].currentPage < tableInfo[tblId].numPages ? tableInfo[tblId].currentPage + 1 : 1; - showPrevNext = 2; - } else if(a.className.search("first-page") != -1) { - tableInfo[tblId].currentPage = 1; - } else if(a.className.search("last-page") != -1) { - tableInfo[tblId].currentPage = tableInfo[tblId].numPages; - } else { - tableInfo[tblId].currentPage = parseInt(a.className.match(/page-([0-9]+)/)[1]) || 1; - }; - - showPage(tblId); - - // Focus on the appropriate button (previous, next or the current page) - // I'm hoping screen readers are savvy enough to indicate the focus event to the user - if(showPrevNext == 1) { - var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-previousPageC" : tblId + "-previousPage"); - } else if(showPrevNext == 2) { - var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-nextPageC" : tblId + "-nextPage"); - } else { - var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-currentPageC" : tblId + "-currentPage"); - }; - - if(elem && elem.tagName.toLowerCase() == "a") { elem.focus(); }; - - return stopEvent(e); - }; - - var onUnLoad = function(e) { - var tbl, lis, pagination, uls; - for(tblId in tableInfo) { - uls = [tblId + "-tablePaginater", tblId + "-tablePaginaterClone"]; - for(var z = 0; z < 2; z++) { - pagination = document.getElementById(uls[z]); - if(!pagination) { continue; }; - lis = pagination.getElementsByTagName("li"); - for(var i = 0, li; li = lis[i]; i++) { - li.onclick = null; - if(li.getElementsByTagName("a").length) { li.getElementsByTagName("a")[0].onclick = null; }; - }; - }; - }; - }; - - addEvent(window, "load", init); - addEvent(window, "unload", onUnLoad); - - return { - init: function(tableId) { init(tableId); }, - redraw: function(tableid, identical) { tableSortRedraw(tableid, identical); }, - tableIsPaginated: function(tableId) { return (tableId in tableInfo); }, - changeTranslations: function(translations) { text = translations; } - }; +/* + paginate table object v2.0 by frequency-decoder.com + + Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/) + + Please credit frequency decoder in any derivative work - thanks + + You are free: + + * to copy, distribute, display, and perform the work + * to make derivative works + * to make commercial use of the work + + Under the following conditions: + + by Attribution. + -------------- + You must attribute the work in the manner specified by the author or licensor. + + sa + -- + 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. + + * For any reuse or distribution, you must make clear to others the license terms of this work. + * Any of these conditions can be waived if you get permission from the copyright holder. +*/ + +var tablePaginater = (function() { + /* + + Localise the button titles here... + + %p is replaced with the appropriate page number + %t is replaced with the total number of pages + + */ + var tableInfo = {}, + uniqueID = 0, + text = ["First Page","Previous Page (Page %p)","Next Page (Page %p)","Last Page (Page %t)","Page %p of %t"]; + + var addClass = function(e,c) { + if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) return; + e.className += ( e.className ? " " : "" ) + c; + }; + + /*@cc_on + /*@if (@_win32) + var removeClass = function(e,c) { + e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1'); + }; + @else @*/ + var removeClass = function(e,c) { + e.className = !c ? "" : (e.className || "").replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; + /*@end + @*/ + + var addEvent = function(obj, type, fn) { + if( obj.attachEvent ) { + obj["e"+type+fn] = fn; + obj[type+fn] = function(){obj["e"+type+fn]( window.event );}; + obj.attachEvent( "on"+type, obj[type+fn] ); + } else { + obj.addEventListener( type, fn, true ); + }; + }; + var removeEvent = function(obj, type, fn) { + try { + if( obj.detachEvent ) { + obj.detachEvent( "on"+type, obj[type+fn] ); + obj[type+fn] = null; + } else { + obj.removeEventListener( type, fn, true ); + }; + } catch(err) {}; + }; + var stopEvent = function(e) { + e = e || window.event; + if(e.stopPropagation) { + e.stopPropagation(); + e.preventDefault(); + }; + + /*@cc_on@*/ + /*@if(@_win32) + e.cancelBubble = true; + e.returnValue = false; + /*@end@*/ + return false; + }; + + var init = function(tableId) { + var tables = tableId && typeof(tableId) == "string" ? [document.getElementById(tableId)] : document.getElementsByTagName('table'), + hook, maxPages, visibleRows, numPages, cp, cb, rowList; + + for(var t = 0, tbl; tbl = tables[t]; t++) { + if(tbl.className.search(/paginate-([0-9]+)/) == -1) { continue; }; + + if(!tbl.id) { tbl.id = "fdUniqueTableId_" + uniqueID++; }; + + maxPages = tbl.className.search(/max-pages-([0-9]+)/) == -1 ? null : Number(tbl.className.match(/max-pages-([0-9]+)/)[1]); + if(maxPages % 2 == 0 && maxPages > 1) { maxPages--; }; + + hook = tbl.getElementsByTagName('tbody'); + hook = (hook.length) ? hook[0] : tbl; + + visibleRows = calculateVisibleRows(hook); + + if(maxPages > (visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1]))) { + maxPages = null; + }; + + numPages = Math.ceil(visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1])); + + if(numPages < 2 && !(tbl.id in tableInfo)) { + continue; + }; + + cp = (tbl.id in tableInfo) ? Math.min(tableInfo[tbl.id].currentPage, numPages) : 1; + + tableInfo[tbl.id] = { + rowsPerPage:Number(tbl.className.match(/paginate-([0-9]+)/)[1]), + currentPage:cp, + totalRows:hook.getElementsByTagName('tr').length, + hook:hook, + maxPages:maxPages, + numPages:numPages, + rowStyle:tbl.className.search(/rowstyle-([\S]+)/) != -1 ? tbl.className.match(/rowstyle-([\S]+)/)[1] : false, + callbacks:parseCallback(/^paginationcallback-/i, /paginationcallback-([\S-]+)/ig, tbl.className) + }; + + showPage(tbl.id); + hook = null; + }; + }; + + var parseCallback = function(head, regExp, cname) { + var cbs = [], + matchs = cname.match(regExp), + parts, obj, func; + + if(!matchs) { return []; }; + + for(var i = 0, mtch; mtch = matchs[i]; i++) { + mtch = mtch.replace(head, "").replace(/-/g, "."); + + try { + if(mtch.indexOf(".") != -1) { + parts = mtch.split('.'); + obj = window; + for (var x = 0, part; part = obj[parts[x]]; x++) { + if(part instanceof Function) { + (function() { + var method = part; + func = function (data) { method.apply(obj, [data]) }; + })(); + } else { + obj = part; + }; + }; + } else { + func = window[mtch]; + }; + + if(!(func instanceof Function)) continue; + cbs[cbs.length] = func; + } catch(err) {}; + }; + + return cbs; + }; + + var callback = function(tblId, opts) { + if(!(tblId in tableInfo) || !(tableInfo[tblId]["callbacks"].length)) return; + for(var i = 0, func; func = tableInfo[tblId]["callbacks"][i]; i++) { + func(opts || {}); + }; + }; + + var calculateVisibleRows = function(hook) { + var trs = hook.rows, + cnt = 0, + reg = /(^|\s)invisibleRow(\s|$)/; + + for(var i = 0, tr; tr = trs[i]; i++) { + if(tr.parentNode != hook || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue; + if(tr.className.search(reg) == -1) { cnt++; }; + }; + + return cnt; + }; + + var createButton = function(details, ul, pseudo) { + var li = document.createElement("li"), + but = document.createElement(pseudo ? "div" : "a"), + span = document.createElement("span"); + + if(!pseudo) { + but.href = "#"; + but.title = details.title; + }; + + but.className = details.className; + + ul.appendChild(li); + li.appendChild(but); + but.appendChild(span); + span.appendChild(document.createTextNode(details.text)); + + if(!pseudo) { + li.onclick = but.onclick = buttonClick; + if(details.id) { but.id = details.id; }; + }; + + li = but = span = null; + }; + var removePagination = function(tableId) { + var wrapT = document.getElementById(tableId + "-fdtablePaginaterWrapTop"), + wrapB = document.getElementById(tableId + "-fdtablePaginaterWrapBottom"); + if(wrapT) { wrapT.parentNode.removeChild(wrapT); }; + if(wrapB) { wrapB.parentNode.removeChild(wrapB); }; + }; + var buildPagination = function(tblId) { + if(!(tblId in tableInfo)) { return; }; + + removePagination(tblId); + + var details = tableInfo[tblId]; + + if(details.numPages < 2) return; + + function resolveText(txt, curr) { + curr = curr || details.currentPage; + return txt.replace("%p", curr).replace("%t", details.numPages); + }; + + if(details.maxPages) { + findex = Math.max(0, Math.floor(Number(details.currentPage - 1) - (Number(details.maxPages - 1) / 2))); + lindex = findex + Number(details.maxPages); + if(lindex > details.numPages) { + lindex = details.numPages; + findex = Math.max(0, details.numPages - Number(details.maxPages)); + }; + } else { + findex = 0; + lindex = details.numPages; + }; + + + var wrapT = document.createElement("div"); + wrapT.className = "fdtablePaginaterWrap"; + wrapT.id = tblId + "-fdtablePaginaterWrapTop"; + + var wrapB = document.createElement("div"); + wrapB.className = "fdtablePaginaterWrap"; + wrapB.id = tblId + "-fdtablePaginaterWrapBottom"; + + // Create list scaffold + var ulT = document.createElement("ul"); + ulT.id = tblId + "-tablePaginater"; + + var ulB = document.createElement("ul"); + ulB.id = tblId + "-tablePaginaterClone"; + ulT.className = ulB.className = "fdtablePaginater"; + + // Add to the wrapper DIVs + wrapT.appendChild(ulT); + wrapB.appendChild(ulB); + + // FIRST (only created if maxPages set) + if(details.maxPages) { + createButton({title:text[0], className:"first-page", text:"\u00ab"}, ulT, !findex); + createButton({title:text[0], className:"first-page", text:"\u00ab"}, ulB, !findex); + }; + + // PREVIOUS (only created if there are more than two pages) + if(details.numPages > 2) { + createButton({title:resolveText(text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPage"}, ulT, details.currentPage == 1); + createButton({title:resolveText(text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPageC"}, ulB, details.currentPage == 1); + }; + + // NUMBERED + for(var i = findex; i < lindex; i++) { + createButton({title:resolveText(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); + createButton({title:resolveText(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); + }; + + // NEXT (only created if there are more than two pages) + if(details.numPages > 2) { + createButton({title:resolveText(text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPage"}, ulT, details.currentPage == details.numPages); + createButton({title:resolveText(text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPageC"}, ulB, details.currentPage == details.numPages); + }; + + // LAST (only created if maxPages set) + if(details.maxPages) { + createButton({title:resolveText(text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulT, lindex == details.numPages); + createButton({title:resolveText(text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulB, lindex == details.numPages); + }; + + // DOM inject wrapper DIVs (FireFox 2.x Bug: this has to be done here if you use display:table) + if(document.getElementById(tblId+"-paginationListWrapTop")) { + document.getElementById(tblId+"-paginationListWrapTop").appendChild(wrapT); + } else { + document.getElementById(tblId).parentNode.insertBefore(wrapT, document.getElementById(tblId)); + }; + + if(document.getElementById(tblId+"-paginationListWrapBottom")) { + document.getElementById(tblId+"-paginationListWrapBottom").appendChild(wrapB); + } else { + document.getElementById(tblId).parentNode.insertBefore(wrapB, document.getElementById(tblId).nextSibling); + }; + }; + + // The tableSort script uses this function to redraw. + var tableSortRedraw = function(tableid, identical) { + if(!tableid || !(tableid in fdTableSort.tableCache) || !(tableid in tableInfo)) { return; }; + + var dataObj = fdTableSort.tableCache[tableid], + data = dataObj.data, + len1 = data.length, + len2 = len1 ? data[0].length - 1 : 0, + hook = dataObj.hook, + colStyle = dataObj.colStyle, + rowStyle = dataObj.rowStyle, + colOrder = dataObj.colOrder, + page = tableInfo[tableid].currentPage - 1, + d1 = tableInfo[tableid].rowsPerPage * page, + d2 = Math.min(tableInfo[tableid].totalRows, d1 + tableInfo[tableid].rowsPerPage), + cnt = 0, + rs = 0, + reg = /(^|\s)invisibleRow(\s|$)/, + tr, tds, cell, pos; + + for(var i = 0; i < len1; i++) { + tr = data[i][len2]; + + if(colStyle) { + tds = tr.cells; + for(thPos in colOrder) { + if(!colOrder[thPos]) removeClass(tds[thPos], colStyle); + else addClass(tds[thPos], colStyle); + }; + }; + + if(tr.className.search(reg) != -1) { continue; }; + + if(!identical) { + cnt++; + + if(cnt > d1 && cnt <= d2) { + if(rowStyle) { + if(rs++ & 1) addClass(tr, rowStyle); + else removeClass(tr, rowStyle); + }; + tr.style.display = ""; + } else { + tr.style.display = "none"; + }; + + // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser + // hook.removeChild(tr); + hook.appendChild(tr); + }; + }; + + tr = tds = hook = null; + }; + + var showPage = function(tblId, pageNum) { + if(!(tblId in tableInfo)) { return; }; + + var page = Math.max(0, !pageNum ? tableInfo[tblId].currentPage - 1 : pageNum - 1), + d1 = tableInfo[tblId].rowsPerPage * page, + d2 = Math.min(tableInfo[tblId].totalRows, d1 + tableInfo[tblId].rowsPerPage), + trs = tableInfo[tblId].hook.rows, + cnt = 0, + rc = 0, + len = trs.length, + rs = tableInfo[tblId].rowStyle, + reg = /(^|\s)invisibleRow(\s|$)/, + row = []; + + for(var i = 0; i < len; i++) { + if(trs[i].className.search(reg) != -1 || trs[i].getElementsByTagName("th").length || (trs[i].parentNode && trs[i].parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) { continue; }; + + cnt++; + + if(cnt > d1 && cnt <= d2) { + if(rs) { + if(rc++ & 1) { + addClass(trs[i], rs); + } else { + removeClass(trs[i], rs); + } + }; + trs[i].style.display = ""; + row[row.length] = trs[i]; + } else { + trs[i].style.display = "none"; + }; + }; + + buildPagination(tblId); + callback(tblId, {"totalRows":len, "currentPage":(page+1), "rowsPerPage":tableInfo[tblId].rowsPerPage, "visibleRows":row}); + }; + + var buttonClick = function(e) { + e = e || window.event; + + var a = this.tagName.toLowerCase() == "a" ? this : this.getElementsByTagName("a")[0]; + + if(a.className.search("currentPage") != -1) return false; + + var ul = this; + while(ul.tagName.toLowerCase() != "ul") ul = ul.parentNode; + + var tblId = ul.id.replace("-tablePaginaterClone","").replace("-tablePaginater", ""); + + tableInfo[tblId].lastPage = tableInfo[tblId].currentPage; + + var showPrevNext = 0; + + if(a.className.search("previous-page") != -1) { + tableInfo[tblId].currentPage = tableInfo[tblId].currentPage > 1 ? tableInfo[tblId].currentPage - 1 : tableInfo[tblId].numPages; + showPrevNext = 1; + } else if(a.className.search("next-page") != -1) { + tableInfo[tblId].currentPage = tableInfo[tblId].currentPage < tableInfo[tblId].numPages ? tableInfo[tblId].currentPage + 1 : 1; + showPrevNext = 2; + } else if(a.className.search("first-page") != -1) { + tableInfo[tblId].currentPage = 1; + } else if(a.className.search("last-page") != -1) { + tableInfo[tblId].currentPage = tableInfo[tblId].numPages; + } else { + tableInfo[tblId].currentPage = parseInt(a.className.match(/page-([0-9]+)/)[1]) || 1; + }; + + showPage(tblId); + + // Focus on the appropriate button (previous, next or the current page) + // I'm hoping screen readers are savvy enough to indicate the focus event to the user + if(showPrevNext == 1) { + var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-previousPageC" : tblId + "-previousPage"); + } else if(showPrevNext == 2) { + var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-nextPageC" : tblId + "-nextPage"); + } else { + var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-currentPageC" : tblId + "-currentPage"); + }; + + if(elem && elem.tagName.toLowerCase() == "a") { elem.focus(); }; + + return stopEvent(e); + }; + + var onUnLoad = function(e) { + var tbl, lis, pagination, uls; + for(tblId in tableInfo) { + uls = [tblId + "-tablePaginater", tblId + "-tablePaginaterClone"]; + for(var z = 0; z < 2; z++) { + pagination = document.getElementById(uls[z]); + if(!pagination) { continue; }; + lis = pagination.getElementsByTagName("li"); + for(var i = 0, li; li = lis[i]; i++) { + li.onclick = null; + if(li.getElementsByTagName("a").length) { li.getElementsByTagName("a")[0].onclick = null; }; + }; + }; + }; + }; + + addEvent(window, "load", init); + addEvent(window, "unload", onUnLoad); + + return { + init: function(tableId) { init(tableId); }, + redraw: function(tableid, identical) { tableSortRedraw(tableid, identical); }, + tableIsPaginated: function(tableId) { return (tableId in tableInfo); }, + changeTranslations: function(translations) { text = translations; } + }; })(); \ No newline at end of file