From 2b82e3ad33774e73c8fde73cf26d3c071c3205e5 Mon Sep 17 00:00:00 2001 From: jdat82 Date: Sat, 6 Feb 2016 19:54:48 +0100 Subject: [PATCH] List of characters with search and incremental rendering. --- app/app.constant.js | 6 ++-- app/characters/_characters.scss | 4 +++ app/characters/characters.controller.js | 47 ++++++++++++++++++++----- app/characters/tab-characters.jade | 20 ++++++----- 4 files changed, 59 insertions(+), 18 deletions(-) diff --git a/app/app.constant.js b/app/app.constant.js index fc38924..f498df6 100644 --- a/app/app.constant.js +++ b/app/app.constant.js @@ -12,11 +12,13 @@ .constant('apiEndpoint', '@@apiEndpoint') .constant('apiKey', '@@apiKey') // Oups, I did it again - .constant('privateApiKey', '@@privateApiKey'); + .constant('privateApiKey', '@@privateApiKey') + // Marvel default offset when requesting a list of results (number of items) + .constant('defaultOffset', 20); // Same as `JSON.stringify` but with indentation. function stringify(value) { return JSON.stringify(value, null, ' '); } -})(); \ No newline at end of file +})(); diff --git a/app/characters/_characters.scss b/app/characters/_characters.scss index 8bd5598..d188167 100644 --- a/app/characters/_characters.scss +++ b/app/characters/_characters.scss @@ -2,4 +2,8 @@ &__form{ width: 100%; } + &__footer{ + text-align: center; + margin: $content-padding $content-padding $content-padding*2 $content-padding; + } } diff --git a/app/characters/characters.controller.js b/app/characters/characters.controller.js index 5627702..062d79c 100644 --- a/app/characters/characters.controller.js +++ b/app/characters/characters.controller.js @@ -5,16 +5,20 @@ .module('app') .controller('CharactersController', CharactersController); - function CharactersController($log, charactersService, $cordovaToast, throwErr, $scope, $cordovaKeyboard) { + function CharactersController($log, charactersService, $cordovaToast, throwErr, defaultOffset, + $cordovaKeyboard) { var vm = this; vm.title = 'CharactersController'; - vm.filter = ''; + vm.filter = 'Deadpool'; // Let's start with something cool ;) - vm.characters = charactersService.getList({nameStartsWith:'Deadpool'}).$object; + vm.characters = []; vm.keep = keep; vm.search = search; vm.searching = false; + vm.loadMore = loadMore; + vm.hasMoreData = hasMoreData; + vm.offset = 0; activate(); @@ -22,6 +26,7 @@ function activate() { $log.debug(vm.title + ' instantiated'); + search(); } function keep() { @@ -29,24 +34,50 @@ } function search() { + vm.searching = true; var criteria = vm.filter ? {nameStartsWith: vm.filter} : {}; var promise = charactersService.getList(criteria); vm.characters = promise.$object; - vm.searching = true; + vm.offset = 0; $cordovaKeyboard.close(); - return promise.then(log).catch(throwErr).finally(hideSpinner); + return promise.then(clean).catch(throwErr); /////////// - function log(characters) { - $log.debug(characters.length + ' results:', characters); + function clean(results) { + var meta = _.get(results, 'meta'); + $log.info('Loaded', meta.count, '/', meta.total, 'characters which name starts with', vm.filter); + vm.searching = false; } - function hideSpinner(){ + } + + function loadMore() { + vm.searching = true; + var criteria = {}; + vm.filter && (criteria.nameStartsWith = vm.filter); + vm.offset += defaultOffset; + criteria.offset = vm.offset; + return charactersService.getList(criteria).then(updateList).catch(throwErr); + + /////////// + + function updateList(results) { + var meta = _.get(results, 'meta'); + $log.info('Loaded', (meta.count + meta.offset), '/', meta.total, 'characters which name starts with', vm.filter); + vm.characters = _.concat(vm.characters, results); + vm.characters.meta = results.meta; vm.searching = false; } + } + function hasMoreData() { + var meta = _.get(vm, 'characters.meta'); + return meta && (meta.count + meta.offset) < meta.total; + } + + } })(); diff --git a/app/characters/tab-characters.jade b/app/characters/tab-characters.jade index 238a408..304726d 100644 --- a/app/characters/tab-characters.jade +++ b/app/characters/tab-characters.jade @@ -5,11 +5,15 @@ ion-view.crt(view-title='Characters') label.item-input-wrapper i.icon.ion-ios-search.placeholder-icon input(type='search', placeholder='Name starts with…', name='name', - ng-model='vm.filter', spellcheck="false") - ion-spinner.spinner-assertive(ng-if='vm.searching') - .list.card(ng-repeat="character in vm.characters track by character.id") - .item.item-image(ui-sref='tab.character-detail({character:character})') - img(ng-src="{{character.getThumbnailUrl()}}") - .item.item-icon-right.assertive - i.icon.ion-android-favorite-outline(ng-click='vm.keep()') - | {{character.name}} + ng-model='vm.filter', spellcheck="false") + .list + .card(ng-repeat="character in vm.characters track by character.id") + .item.item-image(ui-sref='tab.character-detail({character:character})') + img(ng-src="{{character.getThumbnailUrl()}}") + .item.item-icon-right.assertive + i.icon.ion-android-favorite-outline(ng-click='vm.keep()') + | {{character.name}} + .crt__footer + ion-spinner.spinner-assertive(ng-if='vm.searching') + button.button.button-block.button-assertive(ng-click='vm.loadMore()', + ng-show='vm.hasMoreData()') Load more