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

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

#Код. (180158 hits)
#Сортировка выбором, общий подход. (73075 hits)
#Шейкер-сортировка. (71451 hits)
#Сравнение алгоритмов быстрой сортировки. (74088 hits)
#Вычисление среднего, среднего отклонения, среднеквадратического отклонения и дисперсии заданной выборки. (46607 hits)
#Преобразование RGB в HEX и обратно HEX в RGB. (56945 hits)
#Просмотр изображения во всплывающем окне. (89447 hits)
#Разбор строки. (273539 hits)
#Вставка новой записи в таблицу БД. (36717 hits)
#Вычисление двойного интеграла с использованием MPI. (60467 hits)
#Таймер. (40906 hits)
#qForms, библиотека типичного функционала валидации/построения/связки html-форм. (147579 hits)
#Овал, вписанный в прямоугольник. (38054 hits)
#Рисование 3D объекта. (35279 hits)
#сортировка пузырьком. (153159 hits)
#Отслеживание изменений файла. (38054 hits)
#Рисование линии. (38954 hits)
#"The Java Programming Language" Ken Arnold, James Gosling, David Holmes листинги, код, примеры из книги, исходники. (61185 hits)
#Выборка конкретной записи из таблицы. (32980 hits)
#Рисование прямоугольника. (31451 hits)


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

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

Aвтор:
Дата:
Просмотров: 72888
реализации(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]