CodeLAB
на главную карта сайта обратная связь

Популярные задачи:

#Сортировка Шелла, обший принцип. (145435 hits)
#Полезные утилиты, небольшие api и библиотеки и проч.. (69954 hits)
#Переворот символов строки (или элементов одномерного массива). (112650 hits)
#Шифрование произвольных данных. (329171 hits)
#Динамическое формирование выпадающего списка. (52208 hits)
#Постепенное затемнение. (51558 hits)
#Поразрядная сортировка, общий принцип. (131004 hits)
#Овал, вписанный в прямоугольник. (38168 hits)
#ООП на javascript: классы, наследование, инкапсуляция. (257908 hits)
#Постраничный вывод. (72981 hits)
#Валидация, динамическая проверка заполнения html форм. (209564 hits)
#Найти максимальную сумму в последовательности. (137946 hits)
#qForms, библиотека типичного функционала валидации/построения/связки html-форм. (147693 hits)
#Относительный путь к файлу. (40041 hits)
#Рисование линии. (39022 hits)
#Вычисление минимального / максимального значения. (74743 hits)
#Вычисление медианы заданной выборки. (49480 hits)
#Подсветка синтаксиса. (31668 hits)
#Динамическая очистка выпадающего списка (select) на javascript. (91216 hits)
#Арктангенс. (45764 hits)


Главная >> Каталог задач >> Большие объемы данных >>

Постраничный вывод

Aвтор:
Дата:
Просмотров: 72980
реализации(php: 4шт...) +добавить

Введение

Очень распрастраненная задача, как в прикладном, так и в веб- программировании. Хотя в последнем случае - наверное все же ее приходится решать чаще...

Допустим имеется страница с таблицей(гридом и проч.), где нужно выводить огромное количество строк с однотипными данными. Например, этих однотипных элементов - несколько тысяч. Выводить все на одной странице(в одной форме) - довольно неразумно: и пользователю будет трудно воспринимать все это и технически рендеринг/вырисовывание всех этих строк - может занять довольно продолжительное время в зависимости от скорости компьютера пользователя:

data1 data2 data3 ............. dataN
data21 data22 data23 ............. data2N
data31 data32 data33 ............. data3N
..
..
..
..... здесь еще сотни таких строк..
..
...
dataM1 dataM2 dataM3 ............. dataMN

Логичное и самое правильное решение - разбить эту таблицу на несколько страниц, а внизу поставить ссылки(кнопки) переключения на другие страницы.

Формализация

Формализуем задачу.

На входе имеем:

  1. Суммарное количество доступных для просмотра объектов(N)
  2. Максимальное число объектов, которое может отображаться пользователю на одной странице(perPage)
  3. Id страницы, которую нужно отобразить на данный момент. Обычно это либо просто порядковый номер (currPageNum) данной страницы, начиная с 1-ой, либо смещение(currOffset), показывающее сколько объектов нужно пропустить.

На выходе нужно получить список страниц рассмотрев различные варианты, например:

  1. Простой список номеров всех страниц с выделение номера(7) текущей страницы:
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  2. Вариант №1 +ссылки "предыдущая" и "следующая" страницы:
    предыдущая(6) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  следующая(8),
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  следующая(2),
    предыдущая(14) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  3. Расширенный список, отображающий номера страниц, только близлежащие с номером текущей просматриваемой страницы(в пределах некоторого настраиваемого диапазона конечно) +ссылки "предыдущая" и "следующая" страницы:
    предыдущая(6) ... 4 5 6 7 8 9 10 ... следующая(8),
    предыдущая(2) 1 2 3 4 5 6 ... следующая(4),
    предыдущая(13) ... 11 12 13 14 15  следующая(15)
    Поскольку страниц может быть тысячи, поэтому их перечисление будет занимать много места и вообще будет неудобным. Как видно, "настраиваемый диапазон" здесь - это 3 страницы до и 3 после. Конечно, с возможностью менять это число 3 как заблагорассудится.
  4. Вариант 3 +отображение номера первой и последней страницы:
    предыдущая(6) 1 ... 5 6 7 8 9 ... 15  следующая(8)

Рассмотрим каждый из вариантов в отдельности. При этом в качестве id страницы будем использовать смещение как наиболее простой и универсальный вариант.

Простой список

Самый простой соответсвенно алгоритм:

 псевдокод: Простой список  ссылка
  1. // Номер страницы(для пользователя)
  2. currNum = 0
  3. for i = 0; i < N; i += perPage
  4. currNum++
  5. if i == currOffset
  6. print currNum
  7. else
  8. // Выводим номер как ссылку на след.
  9. // страницу, определяя ее через новое
  10. // смещение, которое будет == i
  11. print currNum as <ref> where [offset=i]

 

Простой список +предыдущая и следущая страницы

При этом следует учесть, что если текущая страница - первая или последняя из возможных, то логично будет не отображать ссылку на предыдущую или соответственно на следующую страницу:

 псевдокод: простой список +предыдущая и следующая страницы  ссылка
  1. // Рассчитываем смещение предыдущей страницы
  2. prevOffset = -1;
  3. if currOffset - perPage >= 0
  4. prevOffset = currOffset - perPage;
  5.  
  6. // Рассчитываем смещение для следующей страницы
  7. nextOffset = 0;
  8. if currOffset + perPage < N
  9. nextOffset = currOffset + perPage;
  10.  
  11. // Выводим ссылку(кнопку) на предыдущую страницу
  12. if prevOffset >= 0
  13. print "Previous Page" as <ref> where [offset=prevOffset]
  14.  
  15. // Номер страницы(для пользователя)
  16. currNum = 0
  17.  
  18. for i = 0; i < N; i += perPage
  19. currNum++
  20. if i == offset
  21. print currNum
  22. else
  23. // Выводим номер как ссылку на след.
  24. // страницу, определяя ее через новое
  25. // смещение, которое будет == i
  26. print currNum as <ref> where [offset=i]
  27.  
  28. // Выводим ссылку(кнопку) на следующую страницу
  29. if nextOffset > 0
  30. print "Next Page" as <ref> where [offset=nextOffset]

Обратите внимание на строчку 12: prevOffset вполне возможно может быть нулевым, что будет означать ссылку на первую страницу и будет иметь место при текущей странице - вторая страница.

Расширенный список

Здесь начинается самое интересное, поскольку в этом случае возникает уже довольно много вариантов "сокрытия" ненужных номеров страниц и регулировки этого диапазона сокрытия. Один из них может может выглядеть как:

 псевдокод: Расширенный список  ссылка
  1. // Количество соседних номеров страниц с каждой стороны,
  2. // отображающихся рядом с текущей страницей
  3. // Т.н. упомянутая "регулировка диапазона сокрытия"
  4. xwidth = 3;
  5.  
  6. // Рассчитываем смещение предыдущей страницы
  7. prevOffset = -1;
  8. if currOffset - perPage >= 0
  9. prevOffset = currOffset - perPage;
  10.  
  11. // Рассчитываем смещение для следующей страницы
  12. nextOffset = 0;
  13. if currOffset + perPage < N
  14. nextOffset = currOffset + perPage;
  15.  
  16. // Выводим ссылку(кнопку) на предыдущую страницу
  17. if prevOffset >= 0
  18. print "Previous Page" as <ref> where [offset=prevOffset]
  19.  
  20. // Номер страницы(для пользователя)
  21. currNum = 0
  22.  
  23.  
  24. // Флаги вывода левого и правого многоточия
  25. $leftBlankOut = $rightBlankOut = false;
  26.  
  27. for i = 0; i < N; i += perPage
  28. currNum++
  29.  
  30. // Манипулируем выводом левого многоточия
  31. if (i <= currOffset - xwidth * perPage - perPage)
  32. if (!leftBlankOut) print '...' // Вывод левого многоточия
  33. leftBlankOut = true
  34. continue
  35.  
  36. // Манипулируем выводом правого многоточия
  37. if (i >= currOffset + xwidth * perPage + perPage)
  38. if (!rightBlankOut) print '...' // Вывод правого многоточия
  39. rightBlankOut = true
  40. continue
  41.  
  42. if i == offset
  43. print currNum
  44. else
  45. // Выводим номер как ссылку на след.
  46. // страницу, определяя ее через новое
  47. // смещение, которое будет == i
  48. print currNum as <ref> where [offset=i]
  49.  
  50. // Выводим ссылку(кнопку) на следующую страницу
  51. if nextOffset > 0
  52. print "Next Page" as <ref> where [offset=nextOffset]


Как видим данный алгоритм позволяет легко настраивать дипазаон выводимых номеров вокруг текущего простым изменением переменной xwidth.

Расширеный список + первая и последняя страницы

Для этого нам потребуется внести лишь небольшие изменения в алгоритм предыдущего варианта:

 псевдокод: Расширенный список +первая и последняя страницы  ссылка
  1. // Количество соседних номеров страниц с каждой стороны,
  2. // отображающихся рядом с текущей страницей
  3. // Т.н. упомянутая "регулировка диапазона сокрытия"
  4. xwidth = 3;
  5.  
  6. // Рассчитываем смещение предыдущей страницы
  7. prevOffset = -1;
  8. if currOffset - perPage >= 0
  9. prevOffset = currOffset - perPage;
  10.  
  11. // Рассчитываем смещение для следующей страницы
  12. nextOffset = 0;
  13. if currOffset + perPage < N
  14. nextOffset = currOffset + perPage;
  15.  
  16. // Выводим ссылку(кнопку) на предыдущую страницу
  17. if prevOffset >= 0
  18. print "Previous Page" as <ref> where [offset=prevOffset]
  19.  
  20. // Номер страницы(для пользователя)
  21. currNum = 0
  22.  
  23.  
  24. // Флаги вывода левого и правого многоточия
  25. $leftBlankOut = $rightBlankOut = false;
  26.  
  27. for i = 0; i < N; i += perPage
  28. currNum++
  29.  
  30. // Манипулируем выводом левого многоточия
  31. if (i > 0) && (i <= currOffset - xwidth * perPage - perPage)
  32. if (!leftBlankOut) print '...' // Вывод левого многоточия
  33. leftBlankOut = true
  34. continue
  35.  
  36. // Манипулируем выводом правого многоточия
  37. if (i < N - perPage) && (i >= currOffset + xwidth * perPage + perPage)
  38. if (!rightBlankOut) print '...' // Вывод правого многоточия
  39. rightBlankOut = true
  40. continue
  41.  
  42. if i == offset
  43. print currNum
  44. else
  45. // Выводим номер как ссылку на след.
  46. // страницу, определяя ее через новое
  47. // смещение, которое будет == i
  48. print currNum as <ref> where [offset=i]
  49.  
  50. // Выводим ссылку(кнопку) на следующую страницу
  51. if nextOffset > 0
  52. print "Next Page" as <ref> where [offset=nextOffset]


Как видно по сравнению с предующим вариантом добавились лишь пара условий в строки 31 и 37.

Реализации:

php(4)   +добавить

1) Простой список на php, code #84[автор:this]
2) Простой список +предыдущая/следущая страницы на php, code #85[автор:this]
3) Расширенный список на php, code #86[автор:this]
4) Расширенный список + первая/последняя страницы на php, code #87[автор:this]