Created
March 12, 2017 07:23
-
-
Save Dosant/4c29ecccdc5602e930f092af54e4582e to your computer and use it in GitHub Desktop.
Handle Pagination
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<link rel="stylesheet" href="./styles.css"> | |
</head> | |
<body> | |
<div class="header"> | |
<div class="logo"> | |
Logo | |
</div> | |
</div> | |
<div class="content"> | |
<div class="filter-bar"> | |
<div class="filter-item filter-date">Фильтр по дате: от: <input type="date" /> до: <input type="date" /></div> | |
<div class="filter-item filter-author">Фильтр по автору: <select><option>Все</option><option>Досов Антон</option></select></div> | |
<button>Применить</button> | |
</div> | |
<div class="article-list"> | |
</div> | |
<div class="pagination-bar"> | |
<button id="pagination-show-more">Показать ещё</button> | |
</div> | |
</div> | |
<div class="footer"> | |
<div class="footer-content"> | |
Автор: Досов Антон | |
</div> | |
</div> | |
<!-- templates --> | |
<template id="template-article-list-item"> | |
<div class="article-list-item" data-id="id"> | |
<h3 class="article-list-item-title"> | |
Заголовок статьи | |
</h3> | |
<p class="article-list-item-summary"> | |
Краткое описание для статьи. Тут краткое описание | |
</p> | |
<div class="article-list-item-meta"> | |
<span>Автор: <span class="article-list-item-author">Досов Антон</span></span> | |
<span>Опубликована: <span class="article-list-item-date">12.12.1995 04:35</span></span> | |
</div> | |
</div> | |
</template> | |
<!-- scripts --> | |
<script src="index.js" type="text/javascript"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var articleModel = (function () { | |
var GLOBAL_ARTICLES = [{ | |
"id": "news/2017/02/28/rossiya-snimet-zapret-na-import-moldavskih-vin", | |
"title": "Россия снимет запрет на импорт молдавских вин", | |
"author": "Meduza", | |
"createdAt": new Date("2017-02-28T05:24:23.856Z"), | |
"content": "Content of post", | |
"summary": "Summary of post" | |
}, { | |
"id": "news/2017/02/28/tramp-obvinil-obamu-v-organizatsii-protestov-po-vsey-strane-i-utechek-v-smi", | |
"title": "Трамп обвинил Обаму в организации протестов по всей стране и утечек в СМИ", | |
"author": "Meduza", | |
"createdAt": new Date("2017-02-27T05:24:23.316Z"), | |
"content": "Content of post", | |
"summary": "Summary of post" | |
}, { | |
"id": "news/2017/02/28/rosneft-zainteresovalas-dobychey-v-meksikanskom-zalive", | |
"title": "«Роснефть» заинтересовалась добычей в Мексиканском заливе", | |
"author": "Meduza", | |
"createdAt": new Date("2017-02-26T05:24:22.818Z"), | |
"content": "Content of post", | |
"summary": "Summary of post" | |
}, { | |
"id": "news/2017/02/28/amerikanskiy-senator-predlozhil-nazvat-imenem-nemtsova-ulitsu-pered-posolstvom-rossii", | |
"title": "Американский сенатор предложил назвать именем Немцова улицу перед посольством России", | |
"author": "Meduza", | |
"createdAt": new Date("2017-02-25T05:24:21.043Z"), | |
"content": "Content of post", | |
"summary": "Summary of post" | |
}, { | |
"id": "news/2017/02/28/rossiya-otkazalas-zaderzhat-podozrevaemyh-v-ubiystve-kim-chen-nama", | |
"title": "Россия отказалась задержать подозреваемых в убийстве Ким Чен Нама", | |
"author": "Meduza", | |
"createdAt": new Date("2017-02-24T05:24:19.591Z"), | |
"content": "Content of post", | |
"summary": "Summary of post" | |
}, { | |
"id": "news/2017/02/28/spacex-anonsiroval-polet-kosmicheskih-turistov-k-lune-v-2018-godu", | |
"title": "SpaceX пообещала отправить космических туристов к Луне в 2018 году", | |
"author": "Meduza", | |
"createdAt": new Date("2017-02-22T05:23:51.252Z"), | |
"content": "Content of post", | |
"summary": "Summary of post" | |
}, { | |
"id": "news/2017/02/27/v-avstrii-vyhodtsa-iz-chechni-prigovorili-k-2-5-godam-tyurmy-za-uchastie-v-boyah-na-storone-ig", | |
"title": "В Австрии выходца из Чечни приговорили к 2,5 годам тюрьмы за участие в боях на стороне ИГ", | |
"author": "Meduza", | |
"createdAt": new Date("2017-02-21T05:23:47.871Z"), | |
"content": "Content of post", | |
"summary": "Summary of post" | |
}, { | |
"id": "news/2017/02/27/v-peterburge-zaderzhali-uchastnika-aktsii-lgbt-spetsnaza-proshedshey-23-fevralya", | |
"title": "В Петербурге задержали участника акции «ЛГБТ-спецназа», прошедшей 23 февраля", | |
"author": "Meduza", | |
"createdAt": new Date("2017-01-18T05:23:45.059Z"), | |
"content": "Content of post", | |
"summary": "Summary of post" | |
}, { | |
"id": "news/2017/02/27/nikolay-karachentsov-gospitalizirovan-posle-dtp-v-podmoskovie", | |
"title": "Николай Караченцов госпитализирован после ДТП в Подмосковье", | |
"author": "Meduza", | |
"createdAt": new Date("2017-01-16T05:23:41.378Z"), | |
"content": "Content of post", | |
"summary": "Summary of post" | |
}, { | |
"id": "news/2017/02/27/id-kommersant-nachnet-vypuskat-pod-nazvaniem-dengi-reklamnoe-prilozhenie", | |
"title": "ИД «Коммерсант» начнет выпускать под названием «Деньги» рекламное приложение", | |
"author": "Meduza", | |
"createdAt": new Date("2017-01-15T05:23:36.803Z"), | |
"content": "Content of post", | |
"summary": "Summary of post" | |
}]; | |
function getArticles(skip, top) { | |
skip = skip || 0; | |
top = top || 10; | |
return GLOBAL_ARTICLES.slice(skip, skip + top); | |
} | |
function getArticlesCount() { | |
/* Тут надо учесть текущие фильтры */ | |
return GLOBAL_ARTICLES.length; | |
} | |
return { | |
getArticles: getArticles, | |
getArticlesCount: getArticlesCount | |
}; | |
}()) | |
var articleRenderer = (function () { | |
var ARTICLE_TEMPLATE; | |
var ARTICLE_LIST_NODE; | |
function init() { | |
/* DOM Загрузился. | |
Можно найти в нем нужные элементы и сохранить в переменные */ | |
ARTICLE_TEMPLATE = document.querySelector('#template-article-list-item'); | |
ARTICLE_LIST_NODE = document.querySelector('.article-list'); | |
} | |
function insertArticlesInDOM(articles) { | |
/* для массива объектов статей получим соотвествующие HTML элементы */ | |
var articlesNodes = renderArticles(articles); | |
/* вставим HTML элементы в '.article-list' элемент в DOM. */ | |
articlesNodes.forEach(function (node) { | |
ARTICLE_LIST_NODE.appendChild(node); | |
}); | |
} | |
function removeArticlesFromDom() { | |
ARTICLE_LIST_NODE.innerHTML = ''; | |
} | |
function renderArticles(articles) { | |
/* каждый объект article из массива преобразуем в HTML элемент */ | |
return articles.map(function (article) { | |
return renderArticle(article); | |
}); | |
} | |
function renderArticle(article) { | |
/* | |
Используем template из DOM, заполним его данными конкретной статьи - article. | |
Этот код можно сделать лучше ... | |
*/ | |
var template = ARTICLE_TEMPLATE; | |
template.content.querySelector('.article-list-item').dataset.id = article.id; | |
template.content.querySelector('.article-list-item-title').textContent = article.title; | |
template.content.querySelector('.article-list-item-summary').textContent = article.summary; | |
template.content.querySelector('.article-list-item-author').textContent = article.author; | |
template.content.querySelector('.article-list-item-date').textContent = formatDate(article.createdAt); | |
/* | |
Склонируем полученный контент из template и вернем как результат | |
*/ | |
return template.content.querySelector('.article-list-item').cloneNode(true); | |
} | |
/* Date -> 16/05/2015 09:50 */ | |
function formatDate(d) { | |
return d.getDate() + '/' + (d.getMonth() + 1) + '/' + d.getFullYear() + ' ' + | |
d.getHours() + ':' + d.getMinutes(); | |
} | |
return { | |
init: init, | |
insertArticlesInDOM: insertArticlesInDOM, | |
removeArticlesFromDom: removeArticlesFromDom | |
}; | |
}()); | |
/* | |
Этот модуль будет использоваться для пагинации: | |
1. Содержит в себе данные о текущей странице, сколько всего статей на странице | |
2. Содержит ссылку на кнопку "Показать еще", отбрабатывает клики на кнопку. Прячет кнопку, если больше статей начнет | |
*/ | |
var pagination = (function () { | |
var TOTAL; // всего статей | |
var PER_PAGE = 3; // статей на 1-ой странице | |
var CURRENT_PAGE = 1; // текущая страница | |
var SHOW_MORE_BUTTON; | |
var SHOW_MORE_CALLBACK; // функция, которую вызывать, когда произошел клик по кнопке | |
/* | |
Total: Всего статей в ArticleModel. (Надо будет еще учесть, что total меняется при применении фильтров) | |
showMoreCb: функция, которую надо вызвать при клике на кнопку "Показать Еще" | |
*/ | |
function init(total, showMoreCb) { | |
TOTAL = total; | |
SHOW_MORE_CALLBACK = showMoreCb; | |
SHOW_MORE_BUTTON = document.getElementById('pagination-show-more'); | |
SHOW_MORE_BUTTON.addEventListener('click', handleShowMoreClick) | |
/* Не показывать кнопку если статей нет */ | |
if (getTotalPages() <= CURRENT_PAGE) { | |
hideShowMoreButton(); | |
} | |
/* Вернуть skip, top для начальной отрисовки статей */ | |
return getParams(); | |
} | |
function handleShowMoreClick() { | |
var paginationParams = nextPage(); | |
SHOW_MORE_CALLBACK(paginationParams.skip, paginationParams.top); | |
} | |
function getTotalPages() { | |
return Math.ceil(TOTAL / PER_PAGE); | |
} | |
function nextPage() { | |
CURRENT_PAGE++; | |
if (getTotalPages() <= CURRENT_PAGE) { | |
hideShowMoreButton(); | |
} | |
return getParams(); | |
} | |
function getParams() { | |
return { | |
top: PER_PAGE, | |
skip: (CURRENT_PAGE - 1) * PER_PAGE | |
}; | |
} | |
function hideShowMoreButton() { | |
SHOW_MORE_BUTTON.hidden = true; | |
} | |
return { | |
init: init | |
} | |
}()); | |
/* | |
Функция startApp вызовется, когда браузер полностью загрузит и распарсит исходный HTML (index.html) | |
DOMContentLoaded – означает, что все DOM-элементы разметки уже созданы, | |
можно их искать, вешать обработчики, создавать интерфейс, но при этом, возможно, | |
ещё не догрузились какие-то картинки или стили. | |
*/ | |
document.addEventListener('DOMContentLoaded', startApp); | |
function startApp() { | |
/* DOM Загрузился. | |
Можно найти в нем нужные элементы и сохранить в переменные */ | |
articleRenderer.init(); | |
/* | |
Инициализируем пагинацию. | |
Для это передаем сколько всего статей: total | |
и функцию, которую вызывать при клике на кнопку "Показать Еще": renderArticles | |
*/ | |
var total = articleModel.getArticlesCount(); | |
var paginationParams = pagination.init(total, renderArticles); | |
/* Нарисуем статьи из массива GLOBAL_ARTICLES в DOM */ | |
renderArticles(paginationParams.skip, paginationParams.top); | |
} | |
/* Глобальная Функция для проверки. Свяжет модель и отображение */ | |
function renderArticles(skip, top) { | |
// 1. Достанем нужные статьи из модели | |
var articles = articleModel.getArticles(skip, top); | |
// 2. Отобразим статьи | |
articleRenderer.insertArticlesInDOM(articles); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment