From 8be0ac497debd2a971471c3f01d571c31a2c2d61 Mon Sep 17 00:00:00 2001 From: Frank van Os <frank@sosocio.com> Date: Mon, 25 Jan 2016 14:43:02 +0100 Subject: [PATCH 1/5] ADDED page based pagination --- pagination/dynamic_pagination.js | 227 +++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 pagination/dynamic_pagination.js diff --git a/pagination/dynamic_pagination.js b/pagination/dynamic_pagination.js new file mode 100644 index 0000000..62c5684 --- /dev/null +++ b/pagination/dynamic_pagination.js @@ -0,0 +1,227 @@ +/** + * This pagination plug-in provides multiple navigation types ( Select box, input, or basic navigation ) + * + * To set the limits: + * + * 'maxNormalPages' is used for the maximum pages in normal mode + * 'maxSelectPages' is used for the selectbox mode + * 'maxInputPages' is used for the input mode, + * 'bootstrapTooltip' is used to display max input value for the input mode with bootstrap tooltip plugin + * + * @name Dynamic input,select or basic navigation + * + * @summary Show a `dt-tag select`,`dt-tag input` or basic navigation the user can use to navigate through the tables. + * @author Frank van Os + * + * @example + * $(document).ready(function() { + * $('#example').dataTable( { + * "sPaginationType": "dynamic_pagination" + * } ); + * } ); + */ +$.fn.dataTableExt.oPagination.dynamic_pagination = { + 'maxNormalPages': 10, + 'maxSelectPages': 20, + 'maxInputPages': 50, + 'bootstrapTooltip': false, + 'fnClickHandler': function(e) { + var fnCallbackDraw = e.data.fnCallbackDraw, + oSettings = e.data.oSettings, + sPage = e.data.sPage; + + if ($(this).is(':disabled')) { + return false; + } + + oSettings.oApi._fnPageChange(oSettings, sPage); + fnCallbackDraw(oSettings); + + return true; + }, + /* + * Function: oPagination.dynamic_pagination.fnInit + * Purpose: Initalise dom elements required for pagination with listbox input + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * node:nPaging - the DIV which contains this pagination control + * function:fnCallbackDraw - draw function which must be called on update + */ + "fnInit": function (oSettings, nPaging, fnCallbackDraw) { + + if (oSettings.sTableId !== '') { + $(nPaging).attr('id', oSettings.sTableId + '_paginate'); + } + + var oClasses = oSettings.oClasses, + oLang = oSettings.oLanguage.oPaginate; + + var PagingHolder = $('<ul/>').addClass('pagination'); + var nInputText = $('<input/>').attr('type','text').css('display','none'); + var nInputSelect = $('<select/>').css('display','none').addClass('form-control'); + + var nFirst = $('<li/>').addClass(oClasses.sPageButton+' first').html($('<a/>').attr('href','#').text(oLang.sFirst)); + var nNext = $('<li/>').addClass(oClasses.sPageButton+' next').html($('<a/>').attr('href','#').text(oLang.sNext)); + var nInput = $('<li/>').attr('id',oSettings.sTableId+'_pagination_controls').addClass(oClasses.sPageButton).append(nInputText,nInputSelect); + var nPrev = $('<li/>').addClass(oClasses.sPageButton+' previous').html($('<a/>').attr('href','#').text(oLang.sPrevious)); + var nLast = $('<li/>').addClass(oClasses.sPageButton+' last').html($('<a/>').attr('href','#').text(oLang.sLast)); + + + $(PagingHolder).append(nFirst, nPrev, nInput, nNext, nLast).appendTo(nPaging); + + $(nPaging).on('click','li:not(#'+oSettings.sTableId+'_pagination_controls) a',function (event) { + if(!$(this).parent('li').hasClass('disabled')){ + var nav = $(this).parent('li').attr('class').split(' ').pop(); + + if($.inArray(nav,['first','last','previous','next']) !== -1){ + oSettings.oApi._fnPageChange( oSettings, nav ); + fnCallbackDraw( oSettings ); + } + } + event.preventDefault(); + } ); + + function updatePage(element){ + if (element.val() === '' || element.val().match(/[^0-9]/)) { + /* Nothing entered or non-numeric character */ + element.val() = element.val().replace(/[^\d]/g, ''); // don't even allow anything but digits + return; + } + + var iNewStart = oSettings._iDisplayLength * (element.val() - 1); + if (iNewStart < 0) { + iNewStart = 0; + } + if (iNewStart >= oSettings.fnRecordsDisplay()) { + iNewStart = (Math.ceil((oSettings.fnRecordsDisplay() - 1) / oSettings._iDisplayLength) - 1) * oSettings._iDisplayLength; + } + + oSettings._iDisplayStart = iNewStart; + fnCallbackDraw(oSettings); + } + + $(nInputText).keypress(function (e) { + // On return navigate to given page + if(e.which === 13){ + updatePage($(this)); + } + }); + + $(nInputSelect).change(function (e) { // Set DataTables page property and redraw the grid on listbox change event. + updatePage($(this)); + }); + + /* Disallow text selection */ + $('li.first,li.next,li.previous,li.last').bind( 'selectstart', function (evt) { evt.preventDefault(); } ); + + }, + + /* + * Function: oPagination.listbox.fnUpdate + * Purpose: Update the listbox element + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * function:fnCallbackDraw - draw function which must be called on update + */ + "fnUpdate": function (oSettings, fnCallbackDraw) { + if (!oSettings.aanFeatures.p) { + return; + } + + var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength); + var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1; /* Loop over each instance of the pager */ + var paging = oSettings.aanFeatures.p; + var oClasses = oSettings.oClasses; + var info = oSettings.aanFeatures.i; + var that = this; + + for (var i = 0, iLen = paging.length; i < iLen; i++) { + + if ( oSettings._iDisplayStart === 0 ){ + $(paging).find('.first').attr('class',"paginate_button disabled first"); + $(paging).find('.previous').attr('class',"paginate_button disabled previous"); + } + else { + $(paging).find('.first').attr('class',"paginate_button first"); + $(paging).find('.previous').attr('class',"paginate_button previous"); + } + + if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ){ + $(paging).find('.next').attr('class',"paginate_button disabled next"); + $(paging).find('.last').attr('class',"paginate_button disabled last"); + } + else{ + $(paging).find('.next').attr('class',"paginate_button next"); + $(paging).find('.last').attr('class',"paginate_button last"); + } + + // Hide pagination block and info block + $(paging).hide(); + $(info).hide(); + + if(iPages < that.maxNormalPages){ + $(paging).find('select,input').css('display','none'); + + // Erase + $('#'+oSettings.sTableId+'_pagination_controls').find('a.paginate_button').remove(); + + for (var j = 0; j < iPages; j++) { //add the pages + var oNumber = $('<a/>',{ + 'class': oClasses.sPageButton, + 'aria-controls': oSettings.sTableId, + 'data-dt-idx': j, + 'tabindex': oSettings.iTabIndex + }).text( oSettings.fnFormatNumber(j+1) ); + if (iCurrentPage === j+1) { + oNumber.addClass('active').attr('disabled', true); + } else { + oNumber.click({ 'fnCallbackDraw': fnCallbackDraw, 'oSettings': oSettings, 'sPage': j }, that.fnClickHandler); + } + $(oNumber).appendTo('#'+oSettings.sTableId+'_pagination_controls'); + } + } + else if(iPages > that.maxSelectPages) { + + // Erase + $('#'+oSettings.sTableId+'_pagination_controls').find('a.paginate_button').remove(); + + var inputType = (iPages>that.maxInputPages) ? 'input' : 'select'; + var input = $(paging).find(inputType); + + $(input).css('display','inline'); + + if(oSettings._iDisplayStart === 0 && oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay()){ + $(input).attr('disabled','disabled').attr('class','form-control disabled'); + } + else{ + $(input) + .removeAttr('disabled','disabled') + .attr('class','form-control'); + } + + if(inputType=='select'){ + for (var j = 0; j < iPages; j++) { //add the pages + $(input).append($('<option>', {value:j+1,text:j+1})); + } + $(input).val(iCurrentPage); + + $(paging).find('input').css('display','none'); + } + else if(inputType=='input'){ + if(that.bootstrapTooltip){ + $('.pagination > li > input').attr('data-title','Max. page number: '+iPages).tooltip({ + container: '.pagination', + placement: 'top' + }); + } + $(input).val(iCurrentPage); + $(paging).find('select').css('display','none'); + } + } + + // When there are pages show pagination block and info block + $(paging).show(); + $(info).show(); + } + } +}; \ No newline at end of file From 079321f2743a064de3cac8b1b2101f1bf5fcd44b Mon Sep 17 00:00:00 2001 From: Frank van Os <frank@sosocio.com> Date: Mon, 25 Jan 2016 15:02:19 +0100 Subject: [PATCH 2/5] ADDED clearing selectbox --- pagination/dynamic_pagination.js | 1 + 1 file changed, 1 insertion(+) diff --git a/pagination/dynamic_pagination.js b/pagination/dynamic_pagination.js index 62c5684..84ad2b1 100644 --- a/pagination/dynamic_pagination.js +++ b/pagination/dynamic_pagination.js @@ -200,6 +200,7 @@ $.fn.dataTableExt.oPagination.dynamic_pagination = { } if(inputType=='select'){ + $(input).empty(); for (var j = 0; j < iPages; j++) { //add the pages $(input).append($('<option>', {value:j+1,text:j+1})); } From 90ec7405cd6fe771d8a72673fe6d9e0aee8b892d Mon Sep 17 00:00:00 2001 From: Frank van Os <frank@sosocio.com> Date: Thu, 28 Jan 2016 10:30:46 +0100 Subject: [PATCH 3/5] FIXED checking limits --- pagination/dynamic_pagination.js | 85 ++++++++++++++------------------ 1 file changed, 38 insertions(+), 47 deletions(-) diff --git a/pagination/dynamic_pagination.js b/pagination/dynamic_pagination.js index 84ad2b1..985807c 100644 --- a/pagination/dynamic_pagination.js +++ b/pagination/dynamic_pagination.js @@ -5,12 +5,9 @@ * * 'maxNormalPages' is used for the maximum pages in normal mode * 'maxSelectPages' is used for the selectbox mode - * 'maxInputPages' is used for the input mode, - * 'bootstrapTooltip' is used to display max input value for the input mode with bootstrap tooltip plugin * - * @name Dynamic input,select or basic navigation - * - * @summary Show a `dt-tag select`,`dt-tag input` or basic navigation the user can use to navigate through the tables. + * @name Dynamic input,select list + * @summary Show a `dt-tag select` `dt-tag input` list of pages the user can pick from. * @author Frank van Os * * @example @@ -23,7 +20,6 @@ $.fn.dataTableExt.oPagination.dynamic_pagination = { 'maxNormalPages': 10, 'maxSelectPages': 20, - 'maxInputPages': 50, 'bootstrapTooltip': false, 'fnClickHandler': function(e) { var fnCallbackDraw = e.data.fnCallbackDraw, @@ -84,20 +80,16 @@ $.fn.dataTableExt.oPagination.dynamic_pagination = { function updatePage(element){ if (element.val() === '' || element.val().match(/[^0-9]/)) { /* Nothing entered or non-numeric character */ - element.val() = element.val().replace(/[^\d]/g, ''); // don't even allow anything but digits - return; - } - - var iNewStart = oSettings._iDisplayLength * (element.val() - 1); - if (iNewStart < 0) { - iNewStart = 0; - } - if (iNewStart >= oSettings.fnRecordsDisplay()) { - iNewStart = (Math.ceil((oSettings.fnRecordsDisplay() - 1) / oSettings._iDisplayLength) - 1) * oSettings._iDisplayLength; - } - - oSettings._iDisplayStart = iNewStart; - fnCallbackDraw(oSettings); + return; + } + var iNewStart = oSettings._iDisplayLength * (element.val() - 1); + if (iNewStart > oSettings.fnRecordsDisplay()) { /* Display overrun */ + oSettings._iDisplayStart = (Math.ceil((oSettings.fnRecordsDisplay() - 1) / oSettings._iDisplayLength) - 1) * oSettings._iDisplayLength; + fnCallbackDraw(oSettings); + return; + } + oSettings._iDisplayStart = iNewStart; + fnCallbackDraw(oSettings); } $(nInputText).keypress(function (e) { @@ -135,7 +127,7 @@ $.fn.dataTableExt.oPagination.dynamic_pagination = { var info = oSettings.aanFeatures.i; var that = this; - for (var i = 0, iLen = paging.length; i < iLen; i++) { + for (var i = 0, iLen = paging.length; i < iLen; i++) { if ( oSettings._iDisplayStart === 0 ){ $(paging).find('.first').attr('class',"paginate_button disabled first"); @@ -158,8 +150,8 @@ $.fn.dataTableExt.oPagination.dynamic_pagination = { // Hide pagination block and info block $(paging).hide(); $(info).hide(); - - if(iPages < that.maxNormalPages){ + + if(iPages <= that.maxNormalPages){ $(paging).find('select,input').css('display','none'); // Erase @@ -180,45 +172,44 @@ $.fn.dataTableExt.oPagination.dynamic_pagination = { $(oNumber).appendTo('#'+oSettings.sTableId+'_pagination_controls'); } } - else if(iPages > that.maxSelectPages) { + else if(iPages > that.maxNormalPages && iPages <= that.maxSelectPages) { // Erase $('#'+oSettings.sTableId+'_pagination_controls').find('a.paginate_button').remove(); - var inputType = (iPages>that.maxInputPages) ? 'input' : 'select'; - var input = $(paging).find(inputType); + var input = $(paging).find('select'); - $(input).css('display','inline'); + input.css('display','inline'); if(oSettings._iDisplayStart === 0 && oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay()){ - $(input).attr('disabled','disabled').attr('class','form-control disabled'); + input.attr('disabled','disabled').attr('class','form-control disabled'); } else{ - $(input) + input .removeAttr('disabled','disabled') .attr('class','form-control'); } - if(inputType=='select'){ - $(input).empty(); - for (var j = 0; j < iPages; j++) { //add the pages - $(input).append($('<option>', {value:j+1,text:j+1})); - } - $(input).val(iCurrentPage); + input.empty(); + for (var j = 0; j < iPages; j++) { //add the pages + input.append($('<option>', {value:j+1,text:j+1})); + } + input.val(iCurrentPage); - $(paging).find('input').css('display','none'); - } - else if(inputType=='input'){ - if(that.bootstrapTooltip){ - $('.pagination > li > input').attr('data-title','Max. page number: '+iPages).tooltip({ - container: '.pagination', - placement: 'top' - }); - } - $(input).val(iCurrentPage); - $(paging).find('select').css('display','none'); - } + $(paging).find('input').css('display','none'); } + else if(iPages > that.maxNormalPages && iPages > that.maxSelectPages){ + var input = $(paging).find('input'); + input.css('display','inline'); + if(that.bootstrapTooltip){ + $('.pagination > li > input').attr('data-title','Max. page number: '+iPages).tooltip({ + container: '.pagination', + placement: 'top' + }); + } + input.val(iCurrentPage); + $(paging).find('select').css('display','none'); + } // When there are pages show pagination block and info block $(paging).show(); From 3f214143eb0ffa5e578d78f31875675bb46ab452 Mon Sep 17 00:00:00 2001 From: Frank van Os <frank@sosocio.com> Date: Thu, 28 Jan 2016 10:45:56 +0100 Subject: [PATCH 4/5] ADDED remove pagination buttons --- pagination/dynamic_pagination.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pagination/dynamic_pagination.js b/pagination/dynamic_pagination.js index 985807c..6675b77 100644 --- a/pagination/dynamic_pagination.js +++ b/pagination/dynamic_pagination.js @@ -199,6 +199,9 @@ $.fn.dataTableExt.oPagination.dynamic_pagination = { $(paging).find('input').css('display','none'); } else if(iPages > that.maxNormalPages && iPages > that.maxSelectPages){ + // Remove paging buttons + $('#'+oSettings.sTableId+'_pagination_controls').find('a.paginate_button').remove(); + var input = $(paging).find('input'); input.css('display','inline'); if(that.bootstrapTooltip){ From 8960315a972024703303f1c8b9d6e72d4d5fa00e Mon Sep 17 00:00:00 2001 From: Frank van Os <frank@sosocio.com> Date: Thu, 28 Jan 2016 11:45:28 +0100 Subject: [PATCH 5/5] CHANGED bootstrap tooltip --- pagination/dynamic_pagination.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pagination/dynamic_pagination.js b/pagination/dynamic_pagination.js index 6675b77..a3f9bbb 100644 --- a/pagination/dynamic_pagination.js +++ b/pagination/dynamic_pagination.js @@ -204,14 +204,16 @@ $.fn.dataTableExt.oPagination.dynamic_pagination = { var input = $(paging).find('input'); input.css('display','inline'); + if(that.bootstrapTooltip){ - $('.pagination > li > input').attr('data-title','Max. page number: '+iPages).tooltip({ + input.attr('data-original-title','Max. page number: '+Math.ceil(oSettings.fnRecordsDisplay() / oSettings._iDisplayLength)); + input.tooltip({ container: '.pagination', placement: 'top' }); } input.val(iCurrentPage); - $(paging).find('select').css('display','none'); + $(paging).find('select').css('display','none'); } // When there are pages show pagination block and info block