Algoritmo de paginación inteligente [cerrado]
-
03-07-2019 - |
Pregunta
Estoy buscando un ejemplo de algoritmo de paginación inteligente. Por inteligente, lo que quiero decir es que solo quiero mostrar, por ejemplo, 2 páginas adyacentes a la página actual, por lo que en lugar de terminar con una lista de páginas ridículamente larga, la truncamos.
Este es un ejemplo rápido para que quede más claro ... esto es lo que tengo ahora:
Pages: 1 2 3 4 [5] 6 7 8 9 10 11
Esto es con lo que quiero terminar:
Pages: ... 3 4 [5] 6 7 ...
(En este ejemplo, solo estoy mostrando 2 páginas adyacentes a la página actual)
Lo estoy implementando en PHP / Mysql, y el " basic " La paginación (sin discusión) ya está codificada, solo estoy buscando un ejemplo para optimizarlo ... Puede ser un ejemplo en cualquier idioma, siempre que me dé una idea de cómo implementarlo ...
Solución
Hace un tiempo tuve la misma necesidad.
Aquí está el artículo que usé para hacerlo (con código PHP): Paginación de estilo Digg
Funciona bastante rápido y tiene algunas adiciones a lo que estás tratando de hacer, como:
[1] 2 3 4 5 6 ... 100 1 [2] 3 4 5 6 ... 100 ... 1 ... 4 5 [6] 7 8 ... 100
Aquí está el código del enlace roto:
<?php
/*
Place code to connect to your DB here.
*/
// How many adjacent pages should be shown on each side?
$adjacents = 3;
/*
First get total number of rows in data table.
If you have a WHERE clause in your query, make sure you mirror it here.
*/
$query = "SELECT COUNT(*) as num FROM portfolio";
$total_pages = mysql_fetch_array(mysql_query($query));
$total_pages = $total_pages[num];
/* Setup vars for query. */
$limit = 2; //how many items to show per page
if($page)
$start = ($page - 1) * $limit; //first item to display on this page
else
$start = 0; //if no page var is given, set start to 0
/* Get data. */
$query = "SELECT category, uname, title FROM portfolio LIMIT $start, $limit";
$portfolio = mysql_query($query);
/* Setup page vars for display. */
if ($page == 0) $page = 1; //if no page var is given, default to 1.
$prev = $page - 1; //previous page is page - 1
$next = $page + 1; //next page is page + 1
$lastpage = ceil($total_pages/$limit); //lastpage is = total pages / items per page, rounded up.
$lpm1 = $lastpage - 1; //last page minus 1
/*
Now we apply our rules and draw the pagination object.
We're actually saving the code to a variable in case we want to draw it more than once.
*/
$pagination = "";
if($lastpage > 1)
{
$pagination .= "<div class="\"pagination\"">";
//previous button
if ($page > 1)
$pagination.= "<a href="\"diggstyle.php?page=$prev\"">« previous</a>";
else
$pagination.= "<span class="\"disabled\"">« previous</span>";
//pages
if ($lastpage < 7 + ($adjacents * 2)) //not enough pages to bother breaking it up
{
for ($counter = 1; $counter <= $lastpage; $counter++)
{
if ($counter == $page)
$pagination.= "<span class="\"current\"">$counter</span>";
else
$pagination.= "<a href="\"diggstyle.php?page=$counter\"">$counter</a>";
}
}
elseif($lastpage > 5 + ($adjacents * 2)) //enough pages to hide some
{
//close to beginning; only hide later pages
if($page < 1 + ($adjacents * 2))
{
for ($counter = 1; $counter < 4 + ($adjacents * 2); $counter++)
{
if ($counter == $page)
$pagination.= "<span class="\"current\"">$counter</span>";
else
$pagination.= "<a href="\"diggstyle.php?page=$counter\"">$counter</a>";
}
$pagination.= "...";
$pagination.= "<a href="\"diggstyle.php?page=$lpm1\"">$lpm1</a>";
$pagination.= "<a href="\"diggstyle.php?page=$lastpage\"">$lastpage</a>";
}
//in middle; hide some front and some back
elseif($lastpage - ($adjacents * 2) > $page && $page > ($adjacents * 2))
{
$pagination.= "<a href="\"diggstyle.php?page=1\"">1</a>";
$pagination.= "<a href="\"diggstyle.php?page=2\"">2</a>";
$pagination.= "...";
for ($counter = $page - $adjacents; $counter <= $page + $adjacents; $counter++)
{
if ($counter == $page)
$pagination.= "<span class="\"current\"">$counter</span>";
else
$pagination.= "<a href="\"diggstyle.php?page=$counter\"">$counter</a>";
}
$pagination.= "...";
$pagination.= "<a href="\"diggstyle.php?page=$lpm1\"">$lpm1</a>";
$pagination.= "<a href="\"diggstyle.php?page=$lastpage\"">$lastpage</a>";
}
//close to end; only hide early pages
else
{
$pagination.= "<a href="\"diggstyle.php?page=1\"">1</a>";
$pagination.= "<a href="\"diggstyle.php?page=2\"">2</a>";
$pagination.= "...";
for ($counter = $lastpage - (2 + ($adjacents * 2)); $counter <= $lastpage; $counter++)
{
if ($counter == $page)
$pagination.= "<span class="\"current\"">$counter</span>";
else
$pagination.= "<a href="\"diggstyle.php?page=$counter\"">$counter</a>";
}
}
}
//next button
if ($page < $counter - 1)
$pagination.= "<a href="\"diggstyle.php?page=$next\"">next »</a>";
else
$pagination.= "<span class="\"disabled\"">next »</span>";
$pagination.= "</div>\n";
}
?>
<ul>
<?php
while($item = mysql_fetch_array($portfolio))
{
?>
<li><a href="/web/20080709045706/http://www.strangerstudios.com/portfolio//"></a></li>
<?php
}
?>
</ul>
<?=$pagination?>
Otros consejos
Un poco tarde =), pero aquí está mi intento:
function Pagination($data, $limit = null, $current = null, $adjacents = null)
{
$result = array();
if (isset($data, $limit) === true)
{
$result = range(1, ceil($data / $limit));
if (isset($current, $adjacents) === true)
{
if (($adjacents = floor($adjacents / 2) * 2 + 1) >= 1)
{
$result = array_slice($result, max(0, min(count($result) - $adjacents, intval($current) - ceil($adjacents / 2))), $adjacents);
}
}
}
return $result;
}
Ejemplo :
$total = 1024;
$per_page = 10;
$current_page = 2;
$adjacent_links = 4;
print_r(Pagination($total, $per_page, $current_page, $adjacent_links));
Salida ( @ Codepad ):
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
Otro ejemplo:
$total = 1024;
$per_page = 10;
$current_page = 42;
$adjacent_links = 4;
print_r(Pagination($total, $per_page, $current_page, $adjacent_links));
Salida ( @ Codepad ):
Array
(
[0] => 40
[1] => 41
[2] => 42
[3] => 43
[4] => 44
)
Empecé desde la publicación de lazaro e intenté hacer un algoritmo robusto y ligero con javascript / jquery ... No se necesitan bibliotecas de paginación adicionales y / o voluminosas ... Busque en el violín un ejemplo en vivo: http://jsfiddle.net/97JtZ/1/
var totalPages = 50, buttons = 5;
var currentPage = lowerLimit = upperLimit = Math.min(9, totalPages);
//Search boundaries
for (var b = 1; b < buttons && b < totalPages;) {
if (lowerLimit > 1 ) { lowerLimit--; b++; }
if (b < buttons && upperLimit < totalPages) { upperLimit++; b++; }
}
//Do output to a html element
for (var i = lowerLimit; i <= upperLimit; i++) {
if (i == currentPage) $('#pager').append('<li>' + i + '</li> ');
else $('#pager').append('<a href="#"><li><em>' + i + '</em></li></a> ');
}
Hice una clase de paginación y la puse en Google Code hace un tiempo. Compruébalo es bastante simple. http://code.google.com/p/spaceshipcollaborative/wiki/PHPagination
$paging = new Pagination();
$paging->set('urlscheme','class.pagination.php?page=%page%');
$paging->set('perpage',10);
$paging->set('page',15);
$paging->set('total',3000);
$paging->set('nexttext','Next Page');
$paging->set('prevtext','Previous Page');
$paging->set('focusedclass','selected');
$paging->set('delimiter','');
$paging->set('numlinks',9);
$paging->display();
List<int> pages = new List<int>();
int pn = 2; //example of actual pagenumber
int total = 8;
for(int i = pn - 9; i <= pn + 9; i++)
{
if(i < 1) continue;
if(i > total) break;
pages.Add(i);
}
return pages;
Yo usaría algo simple en la página que está mostrando el paginador, como:
if (
$page_number == 1 || $page_number == $last_page ||
$page_number == $actual_page ||
$page_number == $actual_page+1 || $page_number == $actual_page+2 ||
$page_number == $actual_page-1 || $page_number == $actual_page-2
) echo $page_number;
Puede adaptarlo para mostrar cada una de las 10 páginas con el operador %
...
Creo que usar el caso switch () sería mejor en este caso, simplemente no recuerdo la sintaxis ahora
Mantenlo simple :)
Si es posible generar la paginación en el cliente, sugeriría mi nuevo complemento de Paginación: http://www.xarg.org/2011/09/jquery-pagination-revised/
La solución a tu pregunta sería:
$("#pagination").paging(1000, { // Your number of elements
format: '. - nncnn - ', // Format to get Pages: ... 3 4 [5] 6 7 ...
onSelect: function (page) {
// add code which gets executed when user selects a page
},
onFormat: function (type) {
switch (type) {
case 'block': // n and c
return '<a>' + this.value + '</a>';
case 'fill': // -
return '...';
case 'leap': // .
return 'Pages:';
}
}
});
El código de la paginación CodeIgniter -class se puede encontrar en GitHub
(lo que usted llama) La paginación inteligente se puede lograr mediante la configuración.
$config['num_links'] = 2;
El número de " dígito " enlaces que te gustaría antes y después de la número de página seleccionado. Por ejemplo, el número 2 colocará dos dígitos. a cada lado, como en los enlaces de ejemplo en la parte superior de esta página.