My pagination System currently looks like this:
What my pagination system currently looks like
However, I only want 10 page links to appear at a time. Instead of all of the links.
I have this code:
const nav = document.getElementById('nav');
const content = document.getElementById('content');
let pageIndex = 0;
let itemsPerPage = 3;
let finalPage = Math.ceil(items.length / itemsPerPage) - 1;
console.log(finalPage)
loadItems();
function loadItems() {
content.innerHTML = "";
for (let i = pageIndex * itemsPerPage; i < (pageIndex * itemsPerPage) + itemsPerPage; i++) {
if (!items[i]) break;
const item = document.createElement('div');
item.innerHTML = `
<div>
<img src="${items[i].src}"/>
</div>
<div>
<button>${items[i].desc}</button>
</div>
`;
content.append(item);
}
firstPage();
minusPage();
loadPageNav();
plusPage();
lastPage();
}
function loadPageNav() {
for (let i = 0; i < items.length / itemsPerPage; i++) {
const button = document.createElement('button');
button.classList.add('btn');
button.innerHTML = i + 1;
button.addEventListener('click', (e) => {
pageIndex = e.target.innerHTML - 1;
loadItems();
});
nav.append(button);
}
}
function plusPage() {
const button = document.createElement('button');
button.classList.add('btn');
button.innerHTML = "›";
button.addEventListener('click', () => {
pageIndex = pageIndex + 1;
loadItems();
});
nav.append(button);
if (pageIndex === finalPage) {
button.disabled = true;
}
}
function minusPage() {
const button = document.createElement('button');
button.classList.add('btn');
button.innerHTML = "‹";
button.addEventListener('click', () => {
pageIndex = pageIndex - 1;
loadItems();
});
nav.append(button);
if (pageIndex === 0) {
button.disabled = true;
}
}
function firstPage() {
nav.innerHTML = "";
const button = document.createElement('button');
button.classList.add('btn');
button.innerHTML = "«";
button.addEventListener('click', () => {
pageIndex = 0;
loadItems();
});
nav.append(button);
if (pageIndex === 0) {
button.disabled = true;
}
}
function lastPage() {
const button = document.createElement('button');
button.classList.add('btn');
button.innerHTML = "»";
button.addEventListener('click', () => {
pageIndex = finalPage;
loadItems();
});
nav.append(button);
if (pageIndex === finalPage) {
button.disabled = true;
}
}
This code produces the output shown above. However, I want to produce this output:
What my pagination system should look like
From my understanding, the loadPageNav function is the one that draws your page numbers. Pay attention to the maximum value your for loop goes too.
For example if you have 100 items (items.length = 100) and want to display only 5 items per page then
items.length / itemsPerPage is 100 / 5 = 20.
You have 20 pages and in your loop you create and add a button for each of those. If you want to limit the number of buttons drawn, then you need to limit the maximum value you assign to i.
Related
JS code below catches words from an input as hashtags and turn them to HTML span tag. I just need to put limitation at the amount of words and span tags that are generated by user. For example 10 words. Moreover, by pressing space button the user can delete tags.
const BACKSPACE = 8;
const ENTER = 32;
document.getElementById('tag-input').addEventListener('keydown', adjust);
function adjust(e) {
const val = e.target.value;
if (e.keyCode === BACKSPACE && !val) {
deleteTag();
}
if (e.keyCode === ENTER && val) {
e.target.value = '';
addTag(val);
}
const textLength = textLengthToPx(val);
const inputWidth = e.target.offsetWidth;
const minThreshold = 1;
const maxThreshold = 200;
const delta = inputWidth - textLength;
const shouldGrow = delta < minThreshold;
const shouldShrink = delta > maxThreshold;
if (shouldGrow) {
setStyle(e.target, 'width', '90%');
} else if (shouldShrink) {
e.target.style = '';
}
}
function deleteTag() {
document.querySelectorAll('#tags > span')[document.querySelectorAll('#tags > span').length - 1].remove();
}
function addTag(val) {
const input = document.getElementById('tag-input');
const tag = document.createElement('span');
const tagsContainer = document.getElementById('tags');
tag.className = 'tag';
tag.innerHTML = val;
let counter = 0;
while (counter <= 5) {
tagsContainer.insertBefore(tag, input);
counter++;
}
}
function setStyle(node, rule, value) {
node.style = `${rule}:${value}`;
}
function textLengthToPx(text) {
const span = document.createElement('span');
span.innerHTML = text;
span.className = 'invisible';
return span.offsetWidth;
}
<textarea id="tag-input"></textarea>
Solved the problem by adding a counter.
Hello I want to implement a carousel in Java Script.
When I launch the page the image loads very strangely and the bootstrap carousel does not work. Do I need to import something to make it work? If I make it static in HTML it works. However the task is to load the images with iiif. Also, there would be way too many images to make it static. Also, I would like to have a filter function implemented which only works dynamically.
Can someone help me how to implement the carousel?
Here is all the JS code:
'import bootstrap.js'
function changeIIIFInformation(iiif, size, quality) {
var index = iiif.indexOf('full')
iiif = iiif.substring(0, index)
iiif += "full/"
iiif += "pct:" +size.toString() +"/"
iiif += "0/"
iiif += quality +".jpg"
return iiif
}
function search_period(period, max_num, offset) {
var count = 0;
var link = ""
var div = document.createElement('div')
var div1 = document.createElement ('div')
var a=document.createElement('a')
var span1=document.createElement('span')
var span2=document.createElement('span')
a.setAttribute('class','carousel-control-prev')
a.setAttribute('href','#carouselExampleControls')
a.setAttribute('role','button')
a.setAttribute('data-slide','prev')
span1.setAttribute('class','carousel-control-prev-icon')
span1.setAttribute('aria-hidden', 'true')
span2.setAttribute('class','sr-only')
span2.innerHTML = 'Previous'
div.setAttribute('class', 'carousel slide')
div.setAttribute('data-ride', 'carousel')
div.setAttribute('id', 'carouselExampleControls')
div1.setAttribute('class','carousel-inner')
var h2 = document.createElement('h2')
var iiif = ""
h2.innerHTML = period
document.body.appendChild(h2)
const keys = Object.keys(urls);
for(const elem of keys) {
var label = urls[elem].label
for(const el of urls[elem].variants) {
if(el.label.includes('front')) {
iiif = el.url
}
}
if(!periods.hasOwnProperty(label)) {
continue;
}
if(periods[label] != period) {
continue;
}
if(count < offset) {
count+=1
continue
}
var div2= document.createElement ('div')
div2.setAttribute('class','carousel-item active')
link = changeIIIFInformation(iiif, 10, "default")
var figure = document.createElement('figure')
var figcaption = document.createElement('figcaption')
var linkToImage = document.createElement('a')
//linkToImage.setAttribute('#image', label)
linkToImage.setAttribute('href', 'annotator#'+label)
linkToImage.innerHTML = label
figcaption.appendChild(linkToImage)
var image = document.createElement('img')
image.setAttribute("id", "myimg");
image.setAttribute('src', link)
image.setAttribute('class','d-block w-100')
// figure.appendChild(image)
// figure.appendChild(figcaption)
div.appendChild(div1)
div.appendChild(a)
div1.appendChild(div2)
a.appendChild(span1)
a.appendChild(span2)
div2.appendChild(image)
figure.setAttribute("id", "myFigure");
count += 1;
if(count >= max_num+offset) {
break;
}
}
document.body.appendChild(div)
}
function clear_dom() {
var elements = document.getElementsByTagName('div')
var headings = document.getElementsByTagName('h2')
var buttons = document.getElementsByTagName('button')
while(buttons.length > 0) {
buttons.item(0).remove()
}
while(elements.length > 0) {
elements.item(0).remove()
}
while(headings.length > 0) {
headings.item(0).remove()
}
}
function show_initial_load() {
search_period('Ur III (ca. 2100-2000 BC)', )
}
function show_filtered(selected, offset) {
clear_dom()
search_period(selected, 10, offset)
var previous = document.createElement('button')
if(offset-10 < 0) {
previous.onclick = () => show_filtered(selected, 0)
} else {
previous.onclick = () => show_filtered(selected, offset-10)
}
previous.innerHTML = 'Previous'
document.body.appendChild(previous)
var next = document.createElement('button')
next.onclick = () => show_filtered(selected, offset+10)
next.innerHTML = 'More'
document.body.appendChild(next)
}
function update_view() {
var selected = document.getElementById('perriod-select').value
clear_dom()
if(selected == '') {
show_initial_load()
} else {
show_filtered(selected, 0)
}
}
My problem is When I Select page 2 i want to hide element 0-4 and show 5-8 but when i click 0-4 not hide
I thing because My if condition can some one help me about if condition ? or another way to do ?
and can i limit show data when load first time ?
let data = Array.from(Array(15).keys()).map(item => ({ topic: `Header ${item}`, detail: `Detail ${item}`}))
let tourlek = document.querySelector('#tourlek')
let pagination = document.querySelector('#pagination')
let itemPage = document.getElementsByTagName('item-page')
let item = data.length
let page = 1
let limit = 4
let limitFn = Math.ceil(item / limit)
for (let i = 0; i < item; i++) {
let div = document.createElement('div')
div.textContent = `${data[i].topic} - ${data[i].detail}`
div.classList = 'pd'
tourlek.appendChild(div)
}
for (let i = page; i <= limitFn; i++){
let a = document.createElement('a')
a.textContent = `P:${page}`
// addEventListener onPage function when click
a.addEventListener('click', onPage)
a.setAttribute('data-page', page)
page = page + 1
pagination.appendChild(a).href = 'javascript:void(0)'
}
function onPage (event) {
let itemDom = document.querySelectorAll('.pd')
let currentPage = event.target.getAttribute('data-page')
for (let i = 0; i < itemDom.length; i++) {
if (i >= limit * currentPage ) {
itemDom[i].style.display = 'none'
// console.log(0 < limit * currentPage )
} else {
itemDom[i].style.display = ''
}
}
console.log(event.target.getAttribute('data-page'))
}
a {
margin: 0 10px;
}
<div>
<div id="tourlek"></div>
<div id="pagination"></div>
</div>
To start on page 1 just do
document.querySelector("[data-page='1']").click();
To find the range
const lim = currentPage * limit
for (let i = 0; i < itemDom.length; i++) {
itemDom[i].hidden = i > lim || i < lim -limit
}
let data = Array.from(Array(15).keys()).map(item => ({
topic: `Header ${item}`,
detail: `Detail ${item}`
}))
let tourlek = document.querySelector('#tourlek')
let pagination = document.querySelector('#pagination')
let itemPage = document.getElementsByTagName('item-page')
let currentPage = 1;
let item = data.length
let page = 1
let limit = 4
let limitFn = Math.ceil(item / limit)
let lastPage = 1;
for (let i = 0; i < item; i++) {
let div = document.createElement('div')
div.textContent = `${data[i].topic} - ${data[i].detail}`
div.classList = 'pd'
tourlek.appendChild(div)
}
document.querySelector(".box").addEventListener("click", onPage)
for (let i = page; i <= limitFn; i++) {
let a = document.createElement('a')
a.textContent = `P:${page}`
a.setAttribute('data-page', page)
page = page + 1
pagination.appendChild(a).href = 'javascript:void(0)'
}
document.querySelector("[data-page='1']").click();
function onPage(event) {
const tgt = event.target;
if (tgt.id === "arwL") {
const p = currentPage - 1
if (p===0) return
document.querySelector(`[data-page='${p}']`).click()
return;
}
if (tgt.id === "arwR") {
const p = +currentPage + 1
if (p>=data.length) return
document.querySelector(`[data-page='${p}']`).click()
return;
}
let itemDom = document.querySelectorAll('.pd')
currentPage = event.target.dataset.page;
const lim = currentPage * limit
for (let i = 0; i < itemDom.length; i++) {
itemDom[i].hidden = i > lim || i < lim - limit
}
}
a {
padding: 0 10px;
}
.box {
display: flex;
}
#arwL,
#arwR {
cursor: pointer
}
<div>
<div id="tourlek"></div>
<div class='box'>
<div id="arwL"><</div>
<div id="pagination"></div>
<div id="arwR">></div>
</div>
</div>
let questions = [
{
title: "Commonly used data types DO NOT include:",
choices: ["strings", "booleans", "alerts", "numbers"],
answer: "alerts"
},
{
title: "The condition in an if / else statement is enclosed within ____.",
choices: ["quotes", "curly brackets", "parentheses", "square brackets"],
answer: "parentheses"
}
]
let main = document.getElementById('main');
let content = document.getElementById('content');
let title = document.getElementById('quiz-title');
let instr = document.getElementById('instructions');
let btn = document.getElementById('start-button');
let time = document.getElementById('time');
let h2;
let btns;
let newElement;
let correct;
let questionCounter;
let seconds;
const timer = () => {
time.textContent = seconds;
seconds--;
if (seconds < 0) {
clearInterval(timerStart);
questionCounter = 4;
}
}
var timerStart = setInterval(timer, 1000);
const startQuiz = () => {
title.style.display = 'none';
instr.style.display = 'none';
btn.style.display = 'none';
questionCounter = 0;
newElement = document.createElement('h2');
newElement.textContent = questions[questionCounter].title;
newElement.id = questionCounter;
content.appendChild(newElement);
questions[questionCounter].choices.forEach(function(choice) {
newElement = document.createElement('button');
newElement.textContent = choice;
newElement.setAttribute('class', 'btn btn-success btn-block');
newElement.id = choice;
content.appendChild(newElement);
})
seconds = 10;
timerStart;
};
const advanceQuestion = () => {
document.getElementById(`${questionCounter}-answered`).style.display = 'none';
questionCounter++;
if (questionCounter < 2) {
newElement = document.createElement('h2');
newElement.textContent = questions[questionCounter].title;
newElement.id = questionCounter;
content.appendChild(newElement);
questions[questionCounter].choices.forEach(function(choice) {
newElement = document.createElement('button');
newElement.textContent = choice;
newElement.setAttribute('class', 'btn btn-success btn-block');
newElement.id = choice;
content.appendChild(newElement);
})
} else {
newElement = document.createElement('h2');
newElement.textContent = 'Good job!';
content.appendChild(newElement);
newElement = document.createElement('p');
newElement.textContent = `Your score is ${time.innerHTML}`;
content.appendChild(newElement);
}
}
const checkAnswer = (Event) => {
if (questions[questionCounter].choices.indexOf(Event.target.id) == -1) {
return;
} else {
newElement = document.createElement('h4');
newElement.textContent = 'Answered';
newElement.id = `${questionCounter}-answered`;
content.appendChild(newElement);
}
h2 = document.getElementById(questionCounter)
h2.style.display = 'none';
for (let i = 0; i < questions[questionCounter].choices.length; i++) {
btns = document.getElementById(questions[questionCounter].choices[i]);
btns.style.display = 'none';
}
setTimeout(advanceQuestion, 1000);
}
btn.onclick = startQuiz;
document.onclick = checkAnswer;
main {
text-align: center;
}
section {
width: 80%;
margin: 0 auto;
}
.btn {
margin: 0.5rem 0;
}
#timer {
position: absolute;
top: 0;
right: 0;
}
<header>
<h6 id="high-scores">View Highscores</h6>
<h6 id="timer">Time: <span id="time">0</span></h6>
</header>
<main id="main">
<section id="content">
<h1 id="quiz-title">Coding Quiz Challenge</h1>
<p id="instructions">Try to answer the following code related questions within the time limit. Keep in mind that incorrect answers will penalize your score/time by ten seconds!</p>
<button id="start-button" type="button" class="btn btn-success">Begin Quiz</button>
</section>
</main>
I am new to JavaScript and have been tasked with writing a code quiz application (no jQuery allowed). The application works as follows: the questions are loaded one at a time as answered and a question counter is incremented as it goes. Once the question counter hits the threshold, the quiz ends and the score is displayed. I have added a timer and there is no issue if the quiz is finished within the time given but if the timer reaches 0, the whole application stops working after the clearInterval runs.
const timer = () => {
time.textContent = seconds;
seconds--;
if (seconds < 0) {
clearInterval(timerStart);
questionCounter = 4;
}
}
const timerStart = setInterval(timer, 1000);
The timer is set to 75 seconds in the calling function. The application advances based on the onclick method for what it's worth, and that seems to stop taking inputs after the clearInterval() call. I can post the rest of the code if needed but it is a bit verbose as I am new to this.
EDIT
const advanceQuestion = () => {
if (correct === false) {
document.getElementById(`${questionCounter}-incorrect`).style.display = 'none';
} else {
document.getElementById(`${questionCounter}-correct`).style.display = 'none';
}
questionCounter++;
if (questionCounter < 5) {
newElement = document.createElement('h2');
content.appendChild(newElement);
questions[questionCounter].choices.forEach(function(choice) {
newElement = document.createElement('button');
content.appendChild(newElement);
})
} else {
newElement = document.createElement('h2');
newElement.textContent = 'Good job!';
content.appendChild(newElement);
newElement = document.createElement('p');
newElement.textContent = `Your score is ${time.innerHTML}`;
content.appendChild(newElement);
}
const checkAnswer = (Event) => {
if (Event.target.id === questions[questionCounter].answer) {
newElement = document.createElement('h4');
newElement.textContent = 'Correct!';
content.appendChild(newElement);
} else {
newElement = document.createElement('h4');
newElement.textContent = 'Incorrect';
content.appendChild(newElement);
}
h2 = document.getElementById(questionCounter)
h2.style.display = 'none';
for (let i = 0; i < questions[questionCounter].choices.length; i++) {
btns = document.getElementById(questions[questionCounter].choices[i]);
btns.style.display = 'none';
}
setTimeout(advanceQuestion, 1000);
}
const startQuiz = () => {
title.style.display = 'none';
questionCounter = 0;
newElement = document.createElement('h2');
content.appendChild(newElement);
questions[questionCounter].choices.forEach(function(choice) {
newElement = document.createElement('button');
content.appendChild(newElement);
})
seconds = 10;
timerStart;
btn.onclick = startQuiz;
document.onclick = checkAnswer;
I'm trying to add the numbers of pagination using Javascript. The arrows navigation is working fine but when I try to add the numbers of pages my code doesn't work. I have 2 pages with 10 results each. When I click in the number 1 the console print the number 3. The problem is inside the function createPagination when I create the loop for the page numbers. Any help?
var arrFull = [];
var pageSize = 10;
var pages = -1;
var actualPage = 0;
function changePagination(pagination) {
if(Number(pagination) !== actualPage && pagination > 0 && pagination <= pages) {
var start = ((pagination - 1) * pageSize) + 1;
if(pagination === 1) {
ini = 0;
}
var end = pagination * pageSize;
if(end > arrFull.length) {
end = arrFull.length;
}
var arr = arrFull.slice(start,end);
for(var i = 0; i < arr.length; i++) {
createObject(arr[i]);
}
actualPage = Number(pagination);
createPagination();
}
}
function createPagination() {
var paginator = document.getElementById('pagination');
paginator.innerHTML = "";
var arrowLeft = document.createElement('a');
arrowLeft.setAttribute('href', '');
var arrowRight = document.createElement('a');
arrowRight.setAttribute('href', '');
arrowLeft.innerHTML = '<span class="arrow"></span>';
arrowLeft.addEventListener('click', function(event) {
event.preventDefault();
changePagination(actualPage - 1);
});
arrowRight.innerHTML = '<span class="arrow"></span>';
arrowRight.addEventListener('click', function(event) {
event.preventDefault();
changePagination(actualPage + 1);
});
paginator.appendChild(arrowLeft);
for(var pagination = 1; pagination <= pages; pagination++) {
var number = document.createElement('a');
number.setAttribute('href', '');
number.innerHTML = pagination;
number.addEventListener('click', function(event) {
event.preventDefault();
changePagination(pagination);
console.log(pagination);
});
paginator.appendChild(number);
}
paginator.appendChild(arrowRight);
}
When you pass on your pagination variable it passes the last value set to it in that context (the 3 because of its last iteration in the loop).
You should declare a variable inside the click event and assign to it the value of pagination and then pass your local variable to your method:
number.addEventListener('click', function(event)
{
let currentPage = pagination;
event.preventDefault();
changePagination(currentPage);
console.log(currentPage);
});
That should do the trick.
Edit
This is the actual solution:
number.setAttribute("page", pagination);
number.addEventListener('click', function(event) {
let currentPage = +event.target.getAttribute("page");
event.preventDefault();
changePagination(currentPage);
console.log(currentPage);
});
The reason why the number 3 is being returned is because the let currentPage = pagination; line is being executed when the event triggers; by that time the value of the variable pagination is equal to 3, so you need to save its value through every iteration (it can be saving it inside a property within your element outside of the event scope like so: number._pageNumber = pagination;; or as the given example: number.setAttribute("page", pagination);).
Full implementation
<html>
<body>
<!--Element to simulate the pagination-->
<div id="pagination"></div>
<script>
var arrFull = [];
var pageSize = 10;
var pages = 2; // Change to simulate your case (changed the '-1' to '2')
var actualPage = 0;
function changePagination(pagination) {
if(Number(pagination) !== actualPage && pagination > 0 && pagination <= pages) {
var start = ((pagination - 1) * pageSize) + 1;
if(pagination === 1) {
ini = 0;
}
var end = pagination * pageSize;
if(end > arrFull.length) {
end = arrFull.length;
}
var arr = arrFull.slice(start,end);
for(var i = 0; i < arr.length; i++) {
createObject(arr[i]);
}
actualPage = Number(pagination);
createPagination();
}
}
function createPagination() {
var paginator = document.getElementById('pagination');
paginator.innerHTML = "";
var arrowLeft = document.createElement('a');
arrowLeft.setAttribute('href', '');
var arrowRight = document.createElement('a');
arrowRight.setAttribute('href', '');
arrowLeft.innerHTML = '<span class="arrow"></span>';
arrowLeft.addEventListener('click', function(event) {
event.preventDefault();
changePagination(actualPage - 1);
});
arrowRight.innerHTML = '<span class="arrow"></span>';
arrowRight.addEventListener('click', function(event) {
event.preventDefault();
changePagination(actualPage + 1);
});
paginator.appendChild(arrowLeft);
for(var pagination = 1; pagination <= pages; pagination++) {
var number = document.createElement('a');
number.setAttribute('href', '');
number.innerHTML = pagination;
// <Here_is_the_sugested_code> //
number.setAttribute("page", pagination);
number.addEventListener('click', function(event) {
let currentPage = +event.target.getAttribute("page");
event.preventDefault();
changePagination(currentPage);
console.log(currentPage);
});
// </Here_is_the_sugested_code> //
paginator.appendChild(number);
}
paginator.appendChild(arrowRight);
}
createPagination(); // Call to the function to simulate the generation
</script>
</body>
</html>