backbone pagination current page bug - javascript

im trying to get a pagination in backbone/underscore to work properly. It works fine on init and on next/prev navigation.
But when i try to set the current page on run time it flips out and renders the wrong page numbers. It only gets wrong if i set the current page to something more than 8. Everyting under 8 works fine. Here is my template, it renders only 10 page numbers at a time, credits to
Rida BENHAMMANE!
Template:
<script type="text/template" id="pagination_template">
<section class="pagination">
<ul>
<li>
<div class="paging prev">◄</div>
</li>
<%
var renderPages;
for (var i = 0; i <= pages-1; i++) {
renderPages = false;
if (pages < 10) {
renderPages = true;
} else {
if (current <= 5) {
if (i < 10) {
renderPages = true;
}
} else if (current <= pages - 5) {
if ((current - 5) < i && (current + 5) > i) {
renderPages = true;
}
} else {
if ((pages - 9) < i) {
renderPages = true;
}
}
};
if(renderPages) { %>
<li>
<a href="#" data-offset="<%= i*9 %>" data-page="<%= i %>">
<%= i+1 %>
</a>
</li>
<% }
}
%>
<li>
<div class="paging next">►</div>
</li>
</ul> <br><br>
total pages <%= pages %>
</section>
</script>
And here is the function the changes the current page and renders the navigaton.
Current pages is set to a data-attribute of the clicked element.
updatePageNum: function () {
var self = this;
self.totalModel.fetch({
success:function(model,response) {
var total = response.data;
var p = total/self.perPage;
var r = total-Math.round(p)
self.maxPage = Math.ceil(p);
self.pagination = _.template($("#pagination_template").html(), {
pages:self.maxPage,
current:self.currentPage
});
}
});
},
Anyone that can help on this?

As it has been solved in the comments, I'm posting it as an answer so it can be accepted.
You should wrap your numbers with parseInt():
var total = parseInt(response.data, 10);
var p = parseInt(total/self.perPage, 10);
var r = parseInt(total-Math.round(p), 10);
Cheers.

Related

create pagination for array of objects

I have a nice list of 200 pokemons from pokeapi.co and I have tried to paginate them (20 item/page, 10 pages). I found a nice tutorial, made my own pagination based on that but at the end just doesnt works.
I have tried to call the nextPage, previousPage, firstPage and lastPage. fuctions via HTML button but I get the following error in all 4 cases:
Uncaught ReferenceError: previousPage is not defined
at HTMLButtonElement.onclick (index.html:21)
I am beginner and I dont see the whole picture as clean as a pro, I dont know lot of things and cant figure it out whats wrong with my code!
Please take a look at my code.
Thank you for your time!
//wrapping pokemonList array in an IIFE
const pokemonRepository = (function() {
const pokemonList = [];
const apiUrl = 'https://pokeapi.co/api/v2/pokemon/?limit=200';
//Pagination
var list = new Array();
var pageList = new Array();
var currentPage = 1;
var itemPerPage = 20;
var numberOfPages = 0;
function makeList() {
for (let x = 0; x < 200; x++)
list.push(x);
numberOfPages = getNumberOfPages();
}
function getNumberOfPages() {
return Math.ceil(list.length / itemPerPage);
}
function nextPage() {
currentPage += 1;
loadTheList();
}
function previousPage() {
currentPage -= 1;
loadTheList();
}
function firstPage() {
currentPage = 1;
loadTheList();
}
function lastPage() {
currentPage = numberOfPages;
loadTheList();
}
function loadTheList() {
var begin = ((currentPage - 1) * itemPerPage);
var end = begin + itemPerPage;
pageList = list.slice(begin, end);
drawList(); //draws out our data
check(); //determines the state of the pagination button
}
function drawList() {
document.getElementById('pokemon-list').innerHTML = '';
for (let r = 0; r < pageList.length; r++) {
document.getElementById('pokemon-list').innerHTML += pageList[r] + '';
}
}
function check() {
document.getElementById("next").disabled = currentPage == numberOfPages ? true : false;
document.getElementById("previous").disabled = currentPage == 1 ? true : false;
document.getElementById("first").disabled = currentPage == 1 ? true : false;
document.getElementById("last").disabled = currentPage == numberOfPages ? true : false;
}
function load() {
makeList();
loadTheList();
}
//pagination end
return {
...
};
})();
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
<div id="loading"><h1>Loading...</h1></div>
<h1 class="main-title">Pokédex</h1>
<ul class="pokemon-list" id="pokemon-list">
</ul>
<!-- buttons for pagination-->
<button id="first" onClick="firstPage()">first</button>
<button id="previous" onClick="previousPage()">previous</button>
<button id="next" onClick="nextPage()">next</button>
<button id="last" onClick="lastPage()">last</button>
<script src="js/promise-polyfill.js"></script>
<script src="js/fetch-polyfill.js"></script>
<script src="js/scripts.js"></script>
</body>
</html>

Javascript run 2 functions on button click with multiple buttons and same class

I have a portfolio grid that has a screenshot of past work in each grid item.
Currently on button click, it calls a function to scroll the screenshot and stop once it reaches the bottom of the image.
I need to reverse the scroll once the button is clicked again. The scroll is created by a setInterval. I have a class of "down" on the button which is removed on click.
I have an if statement that does not work to check if the class of "down" is present and run a scrollUp function.
This is a PHP loop so there are multiple buttons with same class.
I cannot use jQuery.
Thanks for any help!
HTML:
<ul>
<li>
<div class="image-container overflow-hidden height-500">
<img class="item absolute pin-t w-full h-auto pin-l"
src="/image.jpg"/>
</div>
<button class="portScroll down">Scroll Down</button>
</li>
<li class="web-design-portfolio">
<div class="image-container overflow-hidden height-500">
<img class="item absolute pin-t w-full h-auto pin-l"
src="/image.jpg"/>
</div>
<button class="portScroll down">Scroll Down</button>
</li>
</ul>
JS:
function scrollDown() {
var portImg = this.parentNode.parentNode.querySelector('img.item');
var height = portImg.clientHeight;
var pos = 0;
var id = setInterval(frame, 5);
function frame() {
if (pos == height - 500) {
clearInterval(id);
} else {
pos++;
portImg.style.top = - + pos + 'px';
}
}
for (const button of document.querySelectorAll('button.portScroll')) {
button.classList.remove('down');
}
}
for (const button of document.querySelectorAll('button.portScroll')) {
if (button.classList.contains("down")) {
button.addEventListener("click", scrollDown);
} else {
button.addEventListener("click", scrollUp);
}
}
Here is the working Codepen for scroll down:
https://codepen.io/completewebco/pen/bZeVoz
I created a single function that does what is needed. I hope that is OK.
function scrollUpOrDown(_this, state) {
var portImg = _this.parentNode.parentNode.querySelector('img.item');
var height = portImg.clientHeight;
if(state.id > -1) {
clearInterval(state.id);
state.dir *= -1;
}
if(state.pos < 0) {
state.pos = 1;
}
state.id = setInterval(frame, 5);
function frame() {
if ((state.pos == height - 500 && state.dir > 0) || (state.pos == 0 && state.dir < 0)) {
clearInterval(state.id);
} else {
state.pos += state.dir;
portImg.style.top = -+state.pos + "px";
}
}
}
for (const button of document.querySelectorAll("button.portScroll")) {
let scollingState = {
pos: -1,
id: -1,
dir: 1
};
if (button.classList.contains("down")) {
button.addEventListener("click", function(){
scrollUpOrDown(this,scollingState);
});
}
}
https://codepen.io/prtjohanson/pen/QoEyQK
If you are wondering why/how it works, look at the output of this code
var array = [0,1,2,3,4,5];
for(const i in array) {
setTimeout(function(){console.log(i)}, Math.random()*1000)
}
and read https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Scoping_rules_2

Paginition refresh issue in AngularJS

I am showing items using pagination in AngularJS.
For example, I have 12 items and number of items per page is 5. So I have 3 pages to show with the first two pages have 5 items each and the last page has two items.
When I switch pages, say from page-1 to page-2, all 10 items from both page-1 and page-2 are displayed together for a while first before the page-2 items are displayed.
Same thing happened from page-2 to page-3, all 7 items from both page-2 and page-3 are displayed together for a while first before the page-3 items are displayed.
Whenever I switch pages, the same thing is observed.
What could be wrong?
My code is as follow.
html
<div class="adds-wrapper">
<div ng-show="Available">
<div class="item-list" ng-repeat="hotel in pagedItems[currentPage]">
<!-- this is how items are displayed -->
</div>
<div class="pagination-bar">
<ul class="pagination">
<li ng-class="{disabled: currentPage == 0}">
<a class="pagination-btn" href ng-click="prevPage()">« Prev</a></li>
<li ng-repeat="n in range(pagedItems.length)" ng-class="{active: n == currentPage}" ng-click="setPage()">
<a href ng-bind="n + 1">1</a>
</li>
<li ng-class="{disabled: currentPage == pagedItems.length - 1}">
<a class="pagination-btn" href ng-click="nextPage()">Next »</a></li>
</ul>
</div>
Javascript
function groupToPages() {
$scope.pagedItems = [];
for (var i = 0; i < $scope.filteredItems.length; i++) {
var j = Math.floor(i / $scope.itemsPerPage);
if (i % $scope.itemsPerPage === 0) {
$scope.pagedItems[j] = [$scope.filteredItems[i]];
} else {
$scope.pagedItems[j].push($scope.filteredItems[i]);
}
}
};
var loadPagination = function () {
$scope.sortingOrder = $scope.sortingOrder;
$scope.reverse = false;
$scope.filteredItems = [];
$scope.groupedItems = [];
$scope.itemsPerPage = 5;
$scope.pagedItems = [];
$scope.currentPage = 0;
$scope.items = $scope.HotelAndResorts;
$scope.filteredItems = $scope.HotelAndResorts;
$scope.hotelAvailable = true;
if ($scope.HotelAndResorts) {
if ($scope.HotelAndResorts.length == 0) {
$scope.hotelAvailable = false;
$scope.errorMessage = "No Post Found.";
}
} else {
$scope.hotelAvailable = false;
$scope.errorMessage = "No Post Found."
}
/*var searchMatch = function (haystack, needle) {
if (!needle) {
return true;
}
return haystack.toLowerCase().indexOf(needle.toLowerCase()) !== -1;
};*/
groupToPages();
$scope.range = function (start, end) {
var ret = [];
if (!end) {
end = start;
start = 0;
}
for (var i = start; i < end; i++) {
ret.push(i);
}
return ret;
};
$scope.prevPage = function () {
if ($scope.currentPage > 0) {
$scope.currentPage--;
}
};
$scope.nextPage = function () {
if ($scope.currentPage < $scope.pagedItems.length - 1) {
$scope.currentPage++;
}
};
$scope.setPage = function () {
$scope.currentPage = this.n;
};
$scope.sort_by = function (newSortingOrder) {
if ($scope.sortingOrder == newSortingOrder)
$scope.reverse = !$scope.reverse;
$scope.sortingOrder = newSortingOrder;
// icon setup
$('th i').each(function () {
// icon reset
$(this).removeClass().addClass('icon-sort');
});
if ($scope.reverse)
$('th.' + new_sorting_order + ' i').removeClass().addClass('icon-chevron-up');
else
$('th.' + new_sorting_order + ' i').removeClass().addClass('icon-chevron-down');
};
}
When you paginate after updating the paged items try calling $scope.apply() this tells AngularJS to look fixup various javascript things. Angular does some sorcery under the hood to make Javascript behave asynchronously, apply makes thing sync up. I'm oversimplifying, if you like you can read the exact documentation, but I find when htis kind of thing happens 95% of the time it's because I didn't apply.

Angular/Javascript - change class after data of ng-repeat reloaded

I am using angularJs with cordova.
I have a ng-repeat, on each items I have a ng-click which put the value of each item in a array. Moreover when I click, it is removing and adding a new class to the div (with the $index of ng-repeat). Like a checklist.
The fact is when, I reload that ng-repeat, I lost the classes I just added when I clicked on it.
I tried (with the array which has not changed) to re-add the class when I call the function that reload the items shown by the ng-repeat. But it doesn't add the class :/
Here are my code :
<div id="ami" class="list-group">
<div href="#" class="list-group-item" ng-repeat="ami in listeAmis"> {{ami.pseudo}}<i id="checkAmi{{$index}}" class="fa fa-circle-o pull-right" ng-click="mapCtrl.checkAmi(ami.pseudo, $index);"></i><i class="fa fa-user pull-left" ></i></div>
</div>
Javascript
var amisNotifies = [];
mapCtrl.checkAmi = checkAmi;
function checkAmi(pseudo, id) {
var info = ({
pseudo: pseudo,
id: id
});
var getIndexOf = function (psdu) {
for (var i = 0; i < amisNotifies.length; i++) {
if (amisNotifies[i].pseudo === psdu) {
return i;
}
}
return -1;
};
if (amisNotifies.length > 0) {
var index = getIndexOf(pseudo);
if (index > -1) {
//so already exists. now remove it.
Array.prototype.splice.call(amisNotifies, index, 1);
$("#checkAmi" + id).addClass("fa-circle-o");
$("#checkAmi" + id).removeClass("fa-check-circle-o");
}
else {
//does not exist, now add it
amisNotifies.push(info);
$("#checkAmi" + id).removeClass("fa-circle-o");
$("#checkAmi" + id).addClass("fa-check-circle-o");
}
} else {
amisNotifies.push(info);
$("#checkAmi" + id).removeClass("fa-circle-o");
$("#checkAmi" + id).addClass("fa-check-circle-o");
}
console.log(amisNotifies);
}
And so, when I reload the data shown by the ng-repeat I tried to put it but it doesn't change the class again...
if (amisNotifies.length > 0) {
for (var i = 0; i < amisNotifies.length; i++) {
console.log(amisNotifies[i].id);
$("#checkAmi" + amisNotifies[i].id).removeClass("fa-circle-o");
$("#checkAmi" + amisNotifies[i].id).addClass("fa-check-circle-o");
}
}
HTML with dynamic ng-class stocked in array depending of the index :
<div id="ami" class="list-group">
<div href="#" class="list-group-item" ng-repeat="ami in listeAmis"> {{ami.pseudo}}
<i id="checkAmi{{$index}}" ng-class="isChecked[{{$index}}]" ng-click="mapCtrl.checkAmi(ami.pseudo, $index);"></i>
</div>
</div>
Declare the numbers of variable depending the size of ng-repeat :
if ($scope.listeAmis.length > 0) {
for (var j = 0; j < $scope.listeAmis.length; j++) {
$scope.isChecked[j] = "fa fa-circle-o pull-right";
}
}
Check the line you just clicked on and change the ng-class (moreover I stock the index of the line a just clicked in order to declare $scope.isChecked[j] differently if I clicked on it ...
mapCtrl.checkAmi = checkAmi;
function checkAmi(pseudo, id) {
var info = ({
pseudo: pseudo,
id: id
});
var getIndexOf = function (psdu) {
for (var i = 0; i < amisNotifies.length; i++) {
if (amisNotifies[i].pseudo === psdu) {
return i;
}
}
return -1;
};
if (amisNotifies.length > 0) {
var index = getIndexOf(pseudo);
if (index > -1) {
//so already exists. now remove it.
Array.prototype.splice.call(amisNotifies, index, 1);
$scope.isChecked[id] = "fa fa-circle-o pull-right";
} else {
//does not exist, now add it
amisNotifies.push(info);
$scope.isChecked[id] = "fa fa-check-circle-o pull-right";
}
} else {
amisNotifies.push(info);
$scope.isChecked[id] = "fa fa-check-circle-o pull-right";
}
console.log(amisNotifies);
}

How do I access and modify an image in an HTML page using javascript?

My HTML page has an image with id img. The idea is that by clicking first, previous, or next, the user can navigate through a set of images. How do I do this using JavaScript?
This should be a good start for you:
<script>
var imgs = ["img1.png","img2.png","img3.png"]; // copy images to the same dir
var index = 0;
</script>
<img src="img1.png" onclick="this.src=imgs[++index%imgs.length]"/>
click the image to slide.
If you need buttons, see this example:
<img id="clicker" src="img1.png"/>
Prev
Next
First
Last
<script>
var imgs = ["img1.png","img2.png","img3.png"];
var index = 0;
var clicker = document.getElementById("clicker");
function prev() { clicker.src = imgs[--index%imgs.length]; }
function next() { clicker.src = imgs[++index%imgs.length]; }
function first() { clicker.src = imgs[index=0]; }
function last() { clicker.src = imgs[index=imgs.length-1]; }
</script>
The return false means that default action on click (follow the link) is supressed. Javascript can access elements i.e. using id (see clicker here). Once you get comfortable with this and you start to solve browser compatibility problems, it is good idea to continue with jQuery (as the other suggests), MooTools or other framework.
Use jQuery!
var myImg = $("#myimg");
$("#next").click(function(){
var id = myImg.attr("data-id") + 1;
myImg.attr("src", "image"+id+".jpg");
});
$("#prev").click(function(){
var id = myImg.attr("data-id") -1;
myImg.attr("src", "image"+id+".jpg");
});
HTML:
<img id="myimg" src="image1.jpg" data-id="1">
Next<br>
Previous<br>
This is a very dummy example. There are numerous slideshow plugins out there!
No need jQuery:
<script type='text/javascript'>
window.onload = function() {
var imageSrcs= ['1.jpeg', '2.jpg', '3.jpg'];
var index = 0;
var image = document.getElementById('img');
var previous = document.getElementById('previous');
previous.onclick = function() {
index -= 1;
if(index < 0) index = imageSrcs.length - 1;
image.src = imageSrcs[index];
}
var next = document.getElementById('next');
next.onclick = function() {
index += 1;
if(index == imageSrcs.length) index = 0;
image.src = imageSrcs[index];
}
}
</script>
And html:
<img src='1.jpeg' id='img'>
<div>
<span id='previous'>Previous</span>
<span id='next'>Next</span>
</div>
You do not need a library for this. Something like this will change the image url, where "theImg" is the id of the image:
document.getElementById("theImg").src = "newUrl.png";
To do it without explicit ids, this will change the url where i is the index of the image:
document.getElementsByTagName("img")[i].src = "newUrl.png";
Try something like this (untested):
LOAD JQUERY:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
JAVASCRIPT:
<script type='text/javascript'>
var lst_src = ['img1.jpg', 'img2.png', 'img3.gif'];
$('a', '#nav').click(function(e) {
e.preventDefault();
var src_current = $('#img').attr('src');
var index = lst_src.indexOf(src_current);
var len = lst_src.length;
var action = $(this).attr('class');
switch ($action) {
case 'previous' : var i = index - 1;
if (i < 0) src_current = lst_src[len + i];
else src_current = lst_src[i];
break;
case 'next' : var i = index + 1;
if (i > len) src_current = lst_src[i - len];
else src_current = lst_src[i];
break;
case 'first' : src_current = lst_src[0];
break;
case 'last' : src_current = lst_src[len - 1];
break;
}
$('#img').attr('src', src_current);
});
</script>
HTML: Use the class of a link to denote the required action:
<img id='img' src='img1.jpg'>
<p id='nav'>
<a href='' class='first'>←←First</a>
<a href='' class='previous'>←Previous</a>
<a href='' class='next'>Next→</a>
<a href='' class='last'>Last→$rarr;</a>
</p>

Categories