Changed pagers to use own spinners; improved looks

This commit is contained in:
Marcin Kurczewski 2014-09-18 11:29:19 +02:00
parent 669b26bda7
commit 2c358b3c77
10 changed files with 190 additions and 132 deletions

View file

@ -6,6 +6,7 @@ body {
color: #555; color: #555;
font-family: 'Droid Sans', sans-serif; font-family: 'Droid Sans', sans-serif;
font-size: 17px; font-size: 17px;
overflow-y: scroll;
} }
h2 { h2 {
@ -15,6 +16,7 @@ h2 {
#middle { #middle {
padding: 0 2em; padding: 0 2em;
position: relative;
} }
#content { #content {
@ -55,19 +57,36 @@ hr {
#wait-cover { #wait-cover {
display: flex; display: flex;
position: fixed; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background: rgba(255, 255, 255, 0.9); min-height: 25em;
background: rgba(255, 255, 255, 0.7);
z-index: 100; z-index: 100;
} }
#wait .spinner { #wait .spinner {
margin: auto; margin: auto;
padding: 1em 2em;
box-shadow: 0 0 1em 1em rgba(255, 255, 255, 0.5);
background: rgba(255, 255, 255, 0.5);
color: #888;
} }
#wait .spinner .fa { #wait .spinner .fa {
font-size: 40px; font-size: 42px;
}
#wait p {
font-size: 15px;
}
.pagination-target .spinner {
display: none;
color: #888;
text-align: center;
}
.pagination-target .spinner .fa {
font-size: 28px;
} }

View file

@ -1,27 +1,16 @@
.pager { .page-list {
text-align: center; text-align: center;
margin-top: 1em;
}
.pager ul {
list-style-type: none; list-style-type: none;
padding: 0; padding: 0;
margin: 0 auto; margin: 1em auto 0 auto;
display: inline-block; display: inline-block;
} }
.pager li { .page-list li {
display: inline-block; display: inline-block;
} }
.pager li a { .page-list li a {
display: inline-block; display: inline-block;
padding: 0.4em 1.2em; padding: 0.4em 1.2em;
} }
.pager li:hover a {
background: #efa;
}
.pager li.active a {
background: #f7fbfc;
}

View file

@ -37,20 +37,20 @@
<div id="main"> <div id="main">
<div id="top-navigation"></div> <div id="top-navigation"></div>
<div id="middle"> <div id="middle">
<div id="sidebar"></div>
<div id="content"></div>
</div>
</div>
<div id="wait"> <div id="wait">
<div id="wait-cover"> <div id="wait-cover">
<div class="spinner"> <div class="spinner">
<i class="fa fa-spin fa-circle-o-notch"></i> <i class="fa fa-spin fa-circle-o-notch"></i>
<p>Loading</p> <p>Loading&hellip;</p>
</div> </div>
</div> </div>
</div> </div>
<div id="sidebar"></div>
<div id="content"></div>
</div>
</div>
<!-- build:template <!-- build:template
<% _.each(templates, function(templateString, templateName) { %> <% _.each(templates, function(templateString, templateName) { %>
<script type="text/template" id="<%= templateName %>-template"> <script type="text/template" id="<%= templateName %>-template">

View file

@ -15,15 +15,23 @@ App.PresenterManager = function(jQuery, topNavigationPresenter) {
presenter.init.call(presenter, args, loaded); presenter.init.call(presenter, args, loaded);
} }
function showContentSpinner() {
$spinner.show();
}
function hideContentSpinner() {
$spinner.hide();
}
function switchContentPresenter(presenter, args) { function switchContentPresenter(presenter, args) {
var contentPresenterLoaded = function() { var contentPresenterLoaded = function() {
window.clearTimeout(spinnerTimeout); window.clearTimeout(spinnerTimeout);
$spinner.hide(); hideContentSpinner();
}; };
spinnerTimeout = window.setTimeout(function() { spinnerTimeout = window.setTimeout(function() {
$spinner.stop().fadeIn('slow'); showContentSpinner();
}, 300); }, 100);
if (lastContentPresenter === null || lastContentPresenter.name !== presenter.name) { if (lastContentPresenter === null || lastContentPresenter.name !== presenter.name) {
topNavigationPresenter.changeTitle(null); topNavigationPresenter.changeTitle(null);
@ -53,6 +61,8 @@ App.PresenterManager = function(jQuery, topNavigationPresenter) {
initPresenter: initPresenter, initPresenter: initPresenter,
initPresenters: initPresenters, initPresenters: initPresenters,
switchContentPresenter: switchContentPresenter, switchContentPresenter: switchContentPresenter,
showContentSpinner: showContentSpinner,
hideContentSpinner: hideContentSpinner,
}; };
}; };

View file

@ -9,13 +9,16 @@ App.Presenters.PagedCollectionPresenter = function(
api, api,
mousetrap, mousetrap,
router, router,
presenterManager,
browsingSettings) { browsingSettings) {
var $target;
var targetContent;
var endlessScroll = browsingSettings.getSettings().endlessScroll; var endlessScroll = browsingSettings.getSettings().endlessScroll;
var scrollInterval; var scrollInterval;
var template; var template;
var totalPages; var totalPages;
var forceClear; var forceClear = false;
var pageNumber; var pageNumber;
var searchParams; var searchParams;
@ -25,9 +28,8 @@ App.Presenters.PagedCollectionPresenter = function(
var failCallback; var failCallback;
function init(args, loaded) { function init(args, loaded) {
forceClear = !_.isEqual(args.searchParams, searchParams) || parseInt(args.page) !== pageNumber + 1; $target = args.$target;
searchParams = args.searchParams; targetContent = jQuery(args.$target).html();
pageNumber = parseInt(args.page) || 1;
baseUri = args.baseUri; baseUri = args.baseUri;
backendUri = args.backendUri; backendUri = args.backendUri;
@ -37,6 +39,17 @@ App.Presenters.PagedCollectionPresenter = function(
promise.wait(util.promiseTemplate('pager')) promise.wait(util.promiseTemplate('pager'))
.then(function(html) { .then(function(html) {
template = _.template(html); template = _.template(html);
render();
loaded();
});
}
function reinit(args, loaded) {
forceClear = !_.isEqual(args.searchParams, searchParams) || parseInt(args.page) !== pageNumber + 1;
searchParams = args.searchParams;
pageNumber = parseInt(args.page) || 1;
softChangePage(pageNumber) softChangePage(pageNumber)
.then(loaded) .then(loaded)
.fail(loaded); .fail(loaded);
@ -53,7 +66,6 @@ App.Presenters.PagedCollectionPresenter = function(
} }
}); });
} }
});
} }
function prevPage() { function prevPage() {
@ -82,9 +94,27 @@ App.Presenters.PagedCollectionPresenter = function(
router.navigate(getPageChangeLink(newPageNumber)); router.navigate(getPageChangeLink(newPageNumber));
} }
function showSpinner() {
if (endlessScroll) {
$target.find('.spinner').show();
} else {
presenterManager.showContentSpinner();
}
}
function hideSpinner() {
if (endlessScroll) {
$target.find('.spinner').hide();
} else {
presenterManager.hideContentSpinner();
}
}
function softChangePage(newPageNumber) { function softChangePage(newPageNumber) {
pageNumber = newPageNumber; pageNumber = newPageNumber;
showSpinner();
return promise.make(function(resolve, reject) { return promise.make(function(resolve, reject) {
promise.wait( promise.wait(
api.get(backendUri, _.extend({}, searchParams, {page: pageNumber}))) api.get(backendUri, _.extend({}, searchParams, {page: pageNumber})))
@ -94,13 +124,15 @@ App.Presenters.PagedCollectionPresenter = function(
var totalRecords = response.json.totalRecords; var totalRecords = response.json.totalRecords;
totalPages = Math.ceil(totalRecords / pageSize); totalPages = Math.ceil(totalRecords / pageSize);
var $target = updateCallback({ updateCallback({
entities: response.json.data, entities: response.json.data,
totalRecords: totalRecords}, totalRecords: totalRecords},
forceClear || !endlessScroll); forceClear || !endlessScroll);
forceClear = false; forceClear = false;
render($target); refreshPageList();
hideSpinner();
attachNextPageLoader();
}).fail(function(response) { }).fail(function(response) {
reject(response); reject(response);
if (typeof(failCallback) !== 'undefined') { if (typeof(failCallback) !== 'undefined') {
@ -112,17 +144,10 @@ App.Presenters.PagedCollectionPresenter = function(
}); });
} }
function render($target) { function attachNextPageLoader() {
var pages = getVisiblePages();
if (!endlessScroll) { if (!endlessScroll) {
$target.find('.pager').remove(); return;
$target.append(template({ }
pages: pages,
pageNumber: pageNumber,
link: getPageChangeLink,
}));
} else {
var $scroller = jQuery('<div/>'); var $scroller = jQuery('<div/>');
window.clearInterval(scrollInterval); window.clearInterval(scrollInterval);
scrollInterval = window.setInterval(function() { scrollInterval = window.setInterval(function() {
@ -133,10 +158,35 @@ App.Presenters.PagedCollectionPresenter = function(
}, 50); }, 50);
$target.append($scroller); $target.append($scroller);
} }
function refreshPageList() {
var pages = getVisiblePages();
$target.find('.page-list').empty();
_.each(pages, function(page) {
var $a = jQuery('<a/>');
$a.addClass('big-button');
$a.attr('href', getPageChangeLink(page));
$a.text(page);
if (page === pageNumber) {
$a.addClass('active');
}
var $li = jQuery('<li/>');
$li.append($a);
$target.find('.page-list').append($li);
});
}
function render() {
$target.html(template({originalHtml: targetContent}));
if (endlessScroll) {
$target.find('.page-list').remove();
} else {
refreshPageList();
}
} }
function getVisiblePages() { function getVisiblePages() {
var pages = [1, totalPages]; var pages = [1, totalPages || 1];
var pagesAroundCurrent = 2; var pagesAroundCurrent = 2;
for (var i = -pagesAroundCurrent; i <= pagesAroundCurrent; i ++) { for (var i = -pagesAroundCurrent; i <= pagesAroundCurrent; i ++) {
if (pageNumber + i >= 1 && pageNumber + i <= totalPages) { if (pageNumber + i >= 1 && pageNumber + i <= totalPages) {
@ -150,11 +200,9 @@ App.Presenters.PagedCollectionPresenter = function(
pages.push(totalPages - 1); pages.push(totalPages - 1);
} }
pages = pages.sort(function(a, b) { return a - b; }).filter(function(item, pos) { return pages.sort(function(a, b) { return a - b; }).filter(function(item, pos) {
return !pos || item !== pages[pos - 1]; return !pos || item !== pages[pos - 1];
}); });
return pages;
} }
function getSearchChangeLink(newSearchParams) { function getSearchChangeLink(newSearchParams) {
@ -167,7 +215,7 @@ App.Presenters.PagedCollectionPresenter = function(
return { return {
init: init, init: init,
render: render, reinit: reinit,
changePage: changePage, changePage: changePage,
getSearchChangeLink: getSearchChangeLink, getSearchChangeLink: getSearchChangeLink,
getPageChangeLink: getPageChangeLink getPageChangeLink: getPageChangeLink
@ -175,4 +223,4 @@ App.Presenters.PagedCollectionPresenter = function(
}; };
App.DI.register('pagedCollectionPresenter', ['_', 'jQuery', 'util', 'promise', 'api', 'mousetrap', 'router', 'browsingSettings'], App.Presenters.PagedCollectionPresenter); App.DI.register('pagedCollectionPresenter', ['_', 'jQuery', 'util', 'promise', 'api', 'mousetrap', 'router', 'presenterManager', 'browsingSettings'], App.Presenters.PagedCollectionPresenter);

View file

@ -28,43 +28,37 @@ App.Presenters.PostListPresenter = function(
itemTemplate = _.template(itemHtml); itemTemplate = _.template(itemHtml);
render(); render();
reinit(args, loaded); loaded();
});
}
function reinit(args, loaded) {
var searchArgs = util.parseComplexRouteArgs(args.searchArgs);
searchArgs.order = searchArgs.order;
updateActiveOrder(searchArgs.order);
initPaginator(searchArgs, loaded);
}
function initPaginator(searchArgs, onLoad) {
pagedCollectionPresenter.init({ pagedCollectionPresenter.init({
page: searchArgs.page,
searchParams: {order: searchArgs.order},
baseUri: '#/posts', baseUri: '#/posts',
backendUri: '/posts', backendUri: '/posts',
$target: $el.find('.pagination-target'),
updateCallback: function(data, clear) { updateCallback: function(data, clear) {
renderPosts(data.entities, clear); renderPosts(data.entities, clear);
return $el.find('.pagination-content');
}, },
failCallback: function(response) { failCallback: function(response) {
$el.empty(); $el.empty();
messagePresenter.showError($el, response.json && response.json.error || response); messagePresenter.showError($el, response.json && response.json.error || response);
}}, onLoad); }
},
function() {
reinit(args, function() {});
});
});
}
function reinit(args, loaded) {
loaded();
var searchArgs = util.parseComplexRouteArgs(args.searchArgs);
pagedCollectionPresenter.reinit({page: searchArgs.page, searchParams: {order: searchArgs.order}});
} }
function render() { function render() {
$el.html(listTemplate()); $el.html(listTemplate());
} }
function updateActiveOrder(activeOrder) {
$el.find('.order li a').removeClass('active');
$el.find('.order [data-order="' + activeOrder + '"]').addClass('active');
}
function renderPosts(posts, clear) { function renderPosts(posts, clear) {
var $target = $el.find('.posts'); var $target = $el.find('.posts');

View file

@ -28,32 +28,34 @@ App.Presenters.UserListPresenter = function(
itemTemplate = _.template(itemHtml); itemTemplate = _.template(itemHtml);
render(); render();
reinit(args, loaded); loaded();
});
}
function reinit(args, loaded) {
var searchArgs = util.parseComplexRouteArgs(args.searchArgs);
searchArgs.order = searchArgs.order || 'name';
updateActiveOrder(searchArgs.order);
initPaginator(searchArgs, loaded);
}
function initPaginator(searchArgs, onLoad) {
pagedCollectionPresenter.init({ pagedCollectionPresenter.init({
page: searchArgs.page,
searchParams: {order: searchArgs.order},
baseUri: '#/users', baseUri: '#/users',
backendUri: '/users', backendUri: '/users',
$target: $el.find('.pagination-target'),
updateCallback: function(data, clear) { updateCallback: function(data, clear) {
renderUsers(data.entities, clear); renderUsers(data.entities, clear);
return $el.find('.pagination-content');
}, },
failCallback: function(response) { failCallback: function(response) {
$el.empty(); $el.empty();
messagePresenter.showError($el, response.json && response.json.error || response); messagePresenter.showError($el, response.json && response.json.error || response);
}}, onLoad); }
},
function() {
reinit(args, function() {});
});
});
}
function reinit(args, loaded) {
loaded();
var searchArgs = util.parseComplexRouteArgs(args.searchArgs);
searchArgs.order = searchArgs.order || 'name';
updateActiveOrder(searchArgs.order);
pagedCollectionPresenter.reinit({page: searchArgs.page, searchParams: {order: searchArgs.order}});
} }
function render() { function render() {

View file

@ -1,15 +1,11 @@
<ul class="pager"> <div class="pagination-content">
<%= originalHtml %>
</div>
<% _.each(pages, function(page) { %> <div class="spinner">
<% if (page == pageNumber) { %> <i class="fa fa-spin fa-circle-o-notch"></i>
<li class="active"> <p>Loading&hellip;</p>
<% } else { %> </div>
<li>
<% } %>
<a href="<%= link(page) %>">
<%= page %>
</a>
</li>
<% }); %>
<ul class="page-list">
</ul> </ul>

View file

@ -1,5 +1,5 @@
<div id="post-list"> <div id="post-list">
<div class="pagination-content"> <div class="pagination-target">
<div class="wrapper"> <div class="wrapper">
<ul class="posts"> <ul class="posts">
</ul> </ul>

View file

@ -14,7 +14,7 @@
</li> </li>
</ul> </ul>
<div class="pagination-content"> <div class="pagination-target">
<ul class="users"> <ul class="users">
</ul> </ul>
</div> </div>