This is the code i got from codepen, it generates special characters and changes to the phrase i put, I'm wanting to compile this vanilla javascript code to react, because you can't use the DOM
there.
My real doubt is where do I put the useState so that it stops looping and shows character by character, this passing for example the state 'title' in a .
vanilla javascript code:
function setCharAt(str,index,chr) {
if(index > str.length-1) return str;
return str.substr(0,index) + chr + str.substr(index+1);
}
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-=+<>,./?[{()}]!##$%^&*~`\|'.split('');
var progress404 = 0;
var total404 = $('.text__error').data('text').length;
var progressLink = 0;
var totalLink = $('.text__link a').data('text').length;
var scrambleInterval = setInterval(function() {
var string404 = $('.text__error').data('text');
var stringLink = $('.text__link a').data('text');
for(var i = 0; i < total404; i++) {
if(i >= progress404) {
string404 = setCharAt(string404, i, characters[Math.round(Math.random() * (characters.length - 1))]);
}
}
for(var i = 0; i < totalLink; i++) {
if(i >= progressLink) {
stringLink = setCharAt(stringLink, i, characters[Math.round(Math.random() * (characters.length - 1))]);
}
}
$('.text__error').text(string404);
$('.text__link a').text(stringLink);
}, 1000 / 60);
setTimeout(function() {
var revealInterval = setInterval(function() {
if(progress404 < total404) {
progress404++;
}else if(progressLink < totalLink) {
progressLink++;
}else{
clearInterval(revealInterval);
clearInterval(scrambleInterval);
}
}, 50);
}, 1000);
This is the code I developed to try to work:
const [ title, setTitle ] = useState('404 page not found')
const [ link, setLink ] = useState('click here to go home')
function setCharAt(str: string,index: number,chr: any) {
if(index > str.length-1) return str;
return str.substr(0,index) + chr + str.substr(index+1);
}
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-=+<>,./?[{()}]!##$%^&*~`\|'.split('');
var progress404 = 0;
var total404 = title.length
var progressLink = 0;
var totalLink = link.length
var scrambleInterval = setInterval(function() {
for(var i = 0; i < total404; i++) {
if(i >= progress404) {
setTitle( setCharAt(title, i, characters[Math.round(Math.random() * (characters.length - 1))]));
}
}
for(var i = 0; i < totalLink; i++) {
if(i >= progressLink) {
setLink( setCharAt(link, i, characters[Math.round(Math.random() * (characters.length - 1))]));
}
}
}, 1000 / 60);
setTimeout(function() {
var revealInterval = setInterval(function() {
if(progress404 < total404) {
progress404++;
}else if(progressLink < totalLink) {
progressLink++;
}else{
clearInterval(revealInterval);
clearInterval(scrambleInterval);
}
}, 50);
}, 1000);
First of all, I hope you can understand my English. I'm not really good at English. I'd like to ask for help on giving 1 point to every unique user(a user that joined, a live stream to be exact) for every correct answer.
The issue I have in the current coding is that instead of giving points to each user respectively, it counts all users as one. What I mean by that is, for example: When user A wins, he gets(displays) 1 point. When user B wins, he gets(displays) 2 points. The points keep adding for every other user.
I'd like it to be like this: When user A wins, he gets(displays) 1 point. When user B wins he also gets(displays) 1 point too. That means each user has their own winning record.
I hope you can understand what I'm trying to explain.
Please ask if you need further explanation on things you don't understand.
I'd like to display the win count under/currently under the 'function addPhoto'.
Following is the current code:
Thanks in advance!
// DATA
let connection = new TikTokIOConnection(undefined);
let gameWords = [];
let gamegameSelectedWord = null;
let gameTimer = null;
let gameStatus = false;
let wins = 0;
// Config
let confComment = false;
let confLike = false;
let confShare = false;
let confJoin = false;
// START
$(document).ready(() => {
// Resize
function resizeContainer() {
let height = window.innerHeight;
let width = Math.round((9 / 16) * height);
$("#gameSize").html(width + 'x' + height);
$(".container").outerWidth(width);
$(".background").outerWidth(width);
$(".printer").outerWidth(width);
$(".animation").outerWidth(width);
// Paper
if (window.innerWidth >= 1366) {
var paperHeight = $("#paperContainer").outerHeight() - 20;
} else {
var paperHeight = $("#paperContainer").outerHeight() + 7;
}
$("#paper").outerHeight(paperHeight);
}
resizeContainer();
$(window).resize(function() {
resizeContainer();
});
// Connect
$("#targetConnect").click(function(e) {
// Check
if (gameStatus) {
let targetLive = $("#targetUsername").val();
connect(targetLive);
} else {
alert("Start game first!");
}
});
// Test
$("#btnPrepare").click(function(e) {
// Check sound
playSound(1);
playSound(2);
playSound(3);
playSound(4);
speakTTS(MSG_TEST);
// Populate dummy
for (let i = 0; i < 30; i++) {
addContent("<div style='text-align:center;'>Welcome 🥳🥳🥳</div>");
}
// Load game
loadGame();
// Setting
loadSetting();
// Set
gameStatus = true;
});
// Save config
$("#btnSave").click(function(e) {
loadSetting();
});
})
/*GAME PLAY
*/
function speakTTS(msg) {
speak(msg, {
amplitude: 100,
pitch: 70,
speed: 150,
wordgap: 5
});
}
/*function scramble( s ) {
return s.replace(
/\b([a-z])([a-z]+)([a-z])\b/gi,
function( t, a, b, c ) {
b = b.split( /\B/ );
for( var i = b.length, j, k; i; j = parseInt( Math.random() * i ),
k = b[--i], b[i] = b[j], b[j] = k ) {}
return a + b.join( '' ) + c;
}
);
}
document.forms.f.onsubmit = function() {
this.elements.t.value = scramble( this.elements.t.value );
return false;
};
document.forms.f.elements.t.value =
scramble( gettext( document.getElementsByTagName( 'p' )[0] ) );
*/
function censor(word) {
let censored = [];
let length = word.length;
let target = Math.ceil(length / 2);
let range_start = 2;
let range_end = target;
for (let i = 0; i < length; i++) {
let c = word.charAt(i);
if (i >= range_start && i <= range_end) {
if (c === " ") {
censored.push(" ");
} else {
censored.push("*");
}
} else {
censored.push(c);
}
}
return censored.join("");
}
function copyArray(a) {
let b = [];
for (i = 0; i < a.length; i++) {
b[i] = a[i];
}
return b;
}
function shuffle(a) {
let j, x, i;
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = a[i];
a[i] = a[j];
a[j] = x;
}
return copyArray(a);
}
function countDown() {
// Counter
let timeleft = 60 * 4; // 4 Mins
// Clear
if (gameTimer != null) {
clearInterval(gameTimer);
}
// Start
gameTimer = setInterval(function() {
// Reset
if (timeleft <= 0){
clearInterval(gameTimer);
loadGame();
}
// Set
$("#gameTimeout").html(timeleft.toLocaleString() + "s");
timeleft -= 1;
}, 1000);
}
function loadGame() {
// Check
if (gameWords.length < 1) {
gameWords = shuffle(WORDS);
}
// Load
gameSelectedWord = gameWords.pop();
// Set remain words
$("#gameWords").html(gameWords.length);
// Check
if (typeof gameSelectedWord === 'string') {
// Normalize
splittedWord = gameSelectedWord.split("|");
gameSelectedWord = splittedWord[1];
// Set
$("#textGuess").html("<div style='font-size:70%;padding-bottom:5px;'>" + splittedWord[0] + "</div>" + censor(gameSelectedWord));
//$("#textGuess").html("<div style='font-size:70%;padding-bottom:5px;'>" + splittedWord[0] + "</div>" + scramble(gameSelectedWord));
// Timeout
countDown()
} else {
loadGame();
}
}
function checkWinner(data, msg) {
// Check type
if (typeof gameSelectedWord === 'string' && typeof msg === 'string') {
// Check answer
if (gameSelectedWord.trim().toLowerCase() == msg.trim().toLowerCase()) {
// Print Photo
addPhoto(data, "winner");
// Sound
playSound(4);
// Play TTS
let tssMsg = MSG_WINNER.replace("|username|", data.uniqueId);
speakTTS(tssMsg);
// Reload game
loadGame();
}
}
}
function loadSetting() {
// Load
confComment = $("#confComment").prop('checked');
confLike = $("#confLike").prop('checked');
confShare = $("#confShare").prop('checked');
confJoin = $("#confJoin").prop('checked');
}
/*LIVE TIKTOK
*/
function connect(targetLive) {
if (targetLive !== '') {
$('#stateText').text('Connecting...');
$("#usernameTarget").html("#"+targetLive);
connection.connect(targetLive, {
enableExtendedGiftInfo: true
}).then(state => {
$('#stateText').text(`Connected ${state.roomId}`);
}).catch(errorMessage => {
$('#stateText').text(errorMessage);
})
} else {
alert('Enter username first!');
}
}
function sanitize(text) {
return text.replace(/</g, '<')
}
function isPendingStreak(data) {
return data.giftType === 1 && !data.repeatEnd;
}
function playSound(mode) {
document.getElementById("sfx"+mode).play();
}
function addContent(payload) {
// Container
let content = $('#paper');
content.append("<div class='item'>" + payload + "</div>");
// Scroll top bottom
content.animate({ scrollTop: content.get(0).scrollHeight}, 333);
}
function addMessage(data, msg) {
// DATA
let userName = data.uniqueId;
let message = sanitize(msg);
// Check for voice
let command = message.split(" ")[0];
if (command == ":=say" || command == ":=cakap") {
// TTS
let cleanText = message.replace("=:say", "").replace("=:cakap", "");
speakTTS(cleanText);
} else {
// Check setting
if (confComment) {
// Add
addContent("<span style='font-weight: bold;'>" + userName + "</span>: " + message);
// Sound
playSound(1);
}
}
}
function addPhoto(data, mode) {
// DATA
let userName = data.uniqueId;
let userAvatar = data.profilePictureUrl;
let word = ['Nice going','That’s better than ever','That’s first class work','I’m impressed','Nothing can stop you now','Well done','Good job','You did it','That’s the way','You rock','I knew you could do it','Keep up the good work','That’s clever','Way to go','Outstanding','Tremendous','Fantastic','You are amazing','No one can beat you','You are the chosen one'];
let words = word[Math.floor(Math.random()*word.length)];
// Add
if (mode == "winner")
{
wins++;
addContent(
`<div style="text-align:center;font-size: 1.25rem;">
<div style='padding-bottom:.25rem;color:#1881FF;'>👏🏻👏🏻 `+words+`</div>
<div style='padding-bottom:.5rem;font-weight: bold;color:#20B601;'>`+userName+` ❗</div>
<div>
<img src="`+userAvatar+`" style="width:135px;height:135px;border-radius: 15px;"/>
Wins: `+wins+`
</div>
</div>`
);
} else {
addContent(
`<div style="text-align:center;font-size: 1.25rem;">
<div style='padding-bottom:.25rem;'>🎉🎉🎉Thanks🎉🎉🎉</div>
<div style='padding-bottom:.5rem;font-weight: bold;color:#EA0C0C;'>`+userName+`</div>
<div>
<img src="`+userAvatar+`" style="width:135px;height:135px;border-radius: 15px;"/>
</div>
</div>`
);
}
// Sound
playSound(3);
}
function addGift(data) {
// DATA
let userName = data.uniqueId;
let giftPictureUrl = data.giftPictureUrl;
let giftName = data.giftName;
let giftRepeat = data.repeatCount;
let giftTotal = (data.diamondCount * data.repeatCount);
let word = ['Appreciate it','Thanks','Thank you very much','It means a lot','You’re the best','Your gift helps me',];
let words = word[Math.floor(Math.random()*word.length)];
// Check
if (giftTotal >= 10) {
// Print Photo
addPhoto(data);
} else {
// Add
addContent(
`<div style="text-align:center;font-size: 1.25rem;"><div style='padding-bottom:.5rem;'>`+words+` <span style='font-weight: bold;color:#EA0C0C;'>`+userName+`!</span></div>
<div style='font-weight: bold;padding-bottom:.5rem;'><img src="`+giftPictureUrl+`" style="width:35px;height:35px;"/> Sent `+giftName+`</div>
x`+giftRepeat.toLocaleString()+` worth `+giftTotal.toLocaleString()+` coins!</div>`
);
// Sound
playSound(2);
// Play TTS
let tssMsg = MSG_GIFT.replace("|username|", userName);
speakTTS(tssMsg);
}
}
// New chat comment received
connection.on('chat', (data) => {
addMessage(data, data.comment);
checkWinner(data, data.comment);
})
// New gift received
connection.on('gift', (data) => {
if (!isPendingStreak(data) && data.diamondCount > 0) {
addGift(data);
}
})
// Like
connection.on('like', (data) => {
if (typeof data.totalLikeCount === 'number') {
// Check setting
if (confLike) {
// Print like
addMessage(data, data.label.replace('{0:user}', '').replace('likes', `${data.likeCount} likes`));
}
}
})
// Share, Follow
connection.on('social', (data) => {
// Check setting
if (confShare) {
// Print share
addMessage(data, data.label.replace('{0:user}', ''));
}
})
// Member join
let joinMsgDelay = 0;
connection.on('member', (data) => {
let addDelay = 250;
if (joinMsgDelay > 500) addDelay = 100;
if (joinMsgDelay > 1000) addDelay = 0;
joinMsgDelay += addDelay;
setTimeout(() => {
joinMsgDelay -= addDelay;
// Check setting
if (confJoin) {
// Print join
addMessage(data, "has entered");
}
}, joinMsgDelay);
})
// End
connection.on('streamEnd', () => {
$('#stateText').text('Stream ended.');
})
You should have an dictionary (object) of wins with keys the users, and values are the wins for each. Thus you save for each user its own wins.
So declare global:
let wins = {
// name: wins, name2: wins2
}
Then whenever need to increase wins, do so for the wins[playerName] value.
if (mode == "winner") {
wins[userName] = wins[userName] || 0
wins[userName]++
addContent(
`<div style="text-align:center;font-size: 1.25rem;">
<div style='padding-bottom:.25rem;color:#1881FF;'>👏🏻👏🏻 `+ words + `</div>
<div style='padding-bottom:.5rem;font-weight: bold;color:#20B601;'>`+ userName + ` ❗</div>
<div>
<img src="`+ userAvatar + `" style="width:135px;height:135px;border-radius: 15px;"/>
Wins: `+ wins[userName] + `
</div>
</div>`
);
}
I am trying to make pagination for my site. (http://anuntorhei.md)
CODE:
var someVar = 50;
function someStupidFunction() {
if (objJson.length > 50) {
document.getElementById("nextPage").style.visibility = "visible";
}
if (someVar <= 50) {
document.getElementById("prevPage").style.visibility ="hidden";
} else {
document.getElementById("prevPage").style.visibility = "visible";
}
}
function nextPage() {
document.getElementById("listingTable").innerHTML = "";
if (someVar < objJson.length) {
document.getElementById("nextPage").style.visibility = "visible";
} else {
document.getElementById("nextPage").style.visibility = "hidden";
}
for (var i = someVar - 50; i < someVar; i++) {
document.getElementById("listingTable").innerHTML += objJson[i].adName + "<br>";
}
someVar += 50;
document.getElementById("prevPage").style.visibility = "visible";
}
function prevPage() {
document.getElementById("listingTable").innerHTML = "";
if (someVar > 50) {
document.getElementById("prevPage").style.visibility = "visible";
} else {
document.getElementById("prevPage").style.visibility = "hidden";
}
for (var i = someVar - 50; i < someVar; i++) {
document.getElementById("listingTable").innerHTML += objJson[i].adName + "<br>";
}
someVar -= 50;
document.getElementById("nextPage").style.visibility = "visible";
}
But I can't understand how to "hide" nextPage button when someVar is bigger than objJson.length.
And when I reach the "end", nextPage button disappear after than objJson is smaller than someVar. What is wrong in this code?
How can I change it to make it perfect? Sorry for my bad English, can't explain all what I need, hope you understand what I need!
I'll address any questions you have... but here is an improved pattern you should follow to reduce code duplication.
As a sidenote though, you should consider not doing pagination on client-side. Since if you have a huge dataset, it would mean you need to download all the data before your page loads. Better to implement server-side pagination instead.
Fiddle: http://jsfiddle.net/Lzp0dw83/
HTML
<div id="listingTable"></div>
Prev
Next
page: <span id="page"></span>
Javascript (put anywhere):
var current_page = 1;
var records_per_page = 2;
var objJson = [
{ adName: "AdName 1"},
{ adName: "AdName 2"},
{ adName: "AdName 3"},
{ adName: "AdName 4"},
{ adName: "AdName 5"},
{ adName: "AdName 6"},
{ adName: "AdName 7"},
{ adName: "AdName 8"},
{ adName: "AdName 9"},
{ adName: "AdName 10"}
]; // Can be obtained from another source, such as your objJson variable
function prevPage()
{
if (current_page > 1) {
current_page--;
changePage(current_page);
}
}
function nextPage()
{
if (current_page < numPages()) {
current_page++;
changePage(current_page);
}
}
function changePage(page)
{
var btn_next = document.getElementById("btn_next");
var btn_prev = document.getElementById("btn_prev");
var listing_table = document.getElementById("listingTable");
var page_span = document.getElementById("page");
// Validate page
if (page < 1) page = 1;
if (page > numPages()) page = numPages();
listing_table.innerHTML = "";
for (var i = (page-1) * records_per_page; i < (page * records_per_page); i++) {
listing_table.innerHTML += objJson[i].adName + "<br>";
}
page_span.innerHTML = page;
if (page == 1) {
btn_prev.style.visibility = "hidden";
} else {
btn_prev.style.visibility = "visible";
}
if (page == numPages()) {
btn_next.style.visibility = "hidden";
} else {
btn_next.style.visibility = "visible";
}
}
function numPages()
{
return Math.ceil(objJson.length / records_per_page);
}
window.onload = function() {
changePage(1);
};
UPDATE 2014/08/27
There is a bug above, where the for loop errors out when a particular page (the last page usually) does not contain records_per_page number of records, as it tries to access a non-existent index.
The fix is simple enough, by adding an extra checking condition into the for loop to account for the size of objJson:
Updated fiddle: http://jsfiddle.net/Lzp0dw83/1/
for (var i = (page-1) * records_per_page; i < (page * records_per_page) && i < objJson.length; i++)
I created a class structure for collections in general that would meet this requirement. and it looks like this:
class Collection {
constructor() {
this.collection = [];
this.index = 0;
}
log() {
return console.log(this.collection);
}
push(value) {
return this.collection.push(value);
}
pushAll(...values) {
return this.collection.push(...values);
}
pop() {
return this.collection.pop();
}
shift() {
return this.collection.shift();
}
unshift(value) {
return this.collection.unshift(value);
}
unshiftAll(...values) {
return this.collection.unshift(...values);
}
remove(index) {
return this.collection.splice(index, 1);
}
add(index, value) {
return this.collection.splice(index, 0, value);
}
replace(index, value) {
return this.collection.splice(index, 1, value);
}
clear() {
this.collection.length = 0;
}
isEmpty() {
return this.collection.length === 0;
}
viewFirst() {
return this.collection[0];
}
viewLast() {
return this.collection[this.collection.length - 1];
}
current(){
if((this.index <= this.collection.length - 1) && (this.index >= 0)){
return this.collection[this.index];
}
else{
return `Object index exceeds collection range.`;
}
}
next() {
this.index++;
this.index > this.collection.length - 1 ? this.index = 0 : this.index;
return this.collection[this.index];
}
previous(){
this.index--;
this.index < 0 ? (this.index = this.collection.length-1) : this.index;
return this.collection[this.index];
}
}
...and essentially what you would do is have a collection of arrays of whatever length for your pages pushed into the class object, and then use the next() and previous() functions to display whatever 'page' (index) you wanted to display. Would essentially look like this:
let books = new Collection();
let firstPage - [['dummyData'], ['dummyData'], ['dummyData'], ['dummyData'], ['dummyData'],];
let secondPage - [['dumberData'], ['dumberData'], ['dumberData'], ['dumberData'], ['dumberData'],];
books.pushAll(firstPage, secondPage); // loads each array individually
books.current() // display firstPage
books.next() // display secondPage
A simple client-side pagination example where data is fetched only once at page loading.
// dummy data
const myarr = [{ "req_no": 1, "title": "test1" },
{ "req_no": 2, "title": "test2" },
{ "req_no": 3, "title": "test3" },
{ "req_no": 4, "title": "test4" },
{ "req_no": 5, "title": "test5" },
{ "req_no": 6, "title": "test6" },
{ "req_no": 7, "title": "test7" },
{ "req_no": 8, "title": "test8" },
{ "req_no": 9, "title": "test9" },
{ "req_no": 10, "title": "test10" },
{ "req_no": 11, "title": "test11" },
{ "req_no": 12, "title": "test12" },
{ "req_no": 13, "title": "test13" },
{ "req_no": 14, "title": "test14" },
{ "req_no": 15, "title": "test15" },
{ "req_no": 16, "title": "test16" },
{ "req_no": 17, "title": "test17" },
{ "req_no": 18, "title": "test18" },
{ "req_no": 19, "title": "test19" },
{ "req_no": 20, "title": "test20" },
{ "req_no": 21, "title": "test21" },
{ "req_no": 22, "title": "test22" },
{ "req_no": 23, "title": "test23" },
{ "req_no": 24, "title": "test24" },
{ "req_no": 25, "title": "test25" },
{ "req_no": 26, "title": "test26" }];
// on page load collect data to load pagination as well as table
const data = { "req_per_page": document.getElementById("req_per_page").value, "page_no": 1 };
// At a time maximum allowed pages to be shown in pagination div
const pagination_visible_pages = 4;
// hide pages from pagination from beginning if more than pagination_visible_pages
function hide_from_beginning(element) {
if (element.style.display === "" || element.style.display === "block") {
element.style.display = "none";
} else {
hide_from_beginning(element.nextSibling);
}
}
// hide pages from pagination ending if more than pagination_visible_pages
function hide_from_end(element) {
if (element.style.display === "" || element.style.display === "block") {
element.style.display = "none";
} else {
hide_from_beginning(element.previousSibling);
}
}
// load data and style for active page
function active_page(element, rows, req_per_page) {
var current_page = document.getElementsByClassName('active');
var next_link = document.getElementById('next_link');
var prev_link = document.getElementById('prev_link');
var next_tab = current_page[0].nextSibling;
var prev_tab = current_page[0].previousSibling;
current_page[0].className = current_page[0].className.replace("active", "");
if (element === "next") {
if (parseInt(next_tab.text).toString() === 'NaN') {
next_tab.previousSibling.className += " active";
next_tab.setAttribute("onclick", "return false");
} else {
next_tab.className += " active"
render_table_rows(rows, parseInt(req_per_page), parseInt(next_tab.text));
if (prev_link.getAttribute("onclick") === "return false") {
prev_link.setAttribute("onclick", `active_page('prev',\"${rows}\",${req_per_page})`);
}
if (next_tab.style.display === "none") {
next_tab.style.display = "block";
hide_from_beginning(prev_link.nextSibling)
}
}
} else if (element === "prev") {
if (parseInt(prev_tab.text).toString() === 'NaN') {
prev_tab.nextSibling.className += " active";
prev_tab.setAttribute("onclick", "return false");
} else {
prev_tab.className += " active";
render_table_rows(rows, parseInt(req_per_page), parseInt(prev_tab.text));
if (next_link.getAttribute("onclick") === "return false") {
next_link.setAttribute("onclick", `active_page('next',\"${rows}\",${req_per_page})`);
}
if (prev_tab.style.display === "none") {
prev_tab.style.display = "block";
hide_from_end(next_link.previousSibling)
}
}
} else {
element.className += "active";
render_table_rows(rows, parseInt(req_per_page), parseInt(element.text));
if (prev_link.getAttribute("onclick") === "return false") {
prev_link.setAttribute("onclick", `active_page('prev',\"${rows}\",${req_per_page})`);
}
if (next_link.getAttribute("onclick") === "return false") {
next_link.setAttribute("onclick", `active_page('next',\"${rows}\",${req_per_page})`);
}
}
}
// Render the table's row in table request-table
function render_table_rows(rows, req_per_page, page_no) {
const response = JSON.parse(window.atob(rows));
const resp = response.slice(req_per_page * (page_no - 1), req_per_page * page_no)
$('#request-table').empty()
$('#request-table').append('<tr><th>Index</th><th>Request No</th><th>Title</th></tr>');
resp.forEach(function (element, index) {
if (Object.keys(element).length > 0) {
const { req_no, title } = element;
const td = `<tr><td>${++index}</td><td>${req_no}</td><td>${title}</td></tr>`;
$('#request-table').append(td)
}
});
}
// Pagination logic implementation
function pagination(data, myarr) {
const all_data = window.btoa(JSON.stringify(myarr));
$(".pagination").empty();
if (data.req_per_page !== 'ALL') {
let pager = `<a href="#" id="prev_link" onclick=active_page('prev',\"${all_data}\",${data.req_per_page})>«</a>` +
`<a href="#" class="active" onclick=active_page(this,\"${all_data}\",${data.req_per_page})>1</a>`;
const total_page = Math.ceil(parseInt(myarr.length) / parseInt(data.req_per_page));
if (total_page < pagination_visible_pages) {
render_table_rows(all_data, data.req_per_page, data.page_no);
for (let num = 2; num <= total_page; num++) {
pager += `<a href="#" onclick=active_page(this,\"${all_data}\",${data.req_per_page})>${num}</a>`;
}
} else {
render_table_rows(all_data, data.req_per_page, data.page_no);
for (let num = 2; num <= pagination_visible_pages; num++) {
pager += `<a href="#" onclick=active_page(this,\"${all_data}\",${data.req_per_page})>${num}</a>`;
}
for (let num = pagination_visible_pages + 1; num <= total_page; num++) {
pager += `<a href="#" style="display:none;" onclick=active_page(this,\"${all_data}\",${data.req_per_page})>${num}</a>`;
}
}
pager += `<a href="#" id="next_link" onclick=active_page('next',\"${all_data}\",${data.req_per_page})>»</a>`;
$(".pagination").append(pager);
} else {
render_table_rows(all_data, myarr.length, 1);
}
}
//calling pagination function
pagination(data, myarr);
// trigger when requests per page dropdown changes
function filter_requests() {
const data = { "req_per_page": document.getElementById("req_per_page").value, "page_no": 1 };
pagination(data, myarr);
}
.box {
float: left;
padding: 50px 0px;
}
.clearfix::after {
clear: both;
display: table;
}
.options {
margin: 5px 0px 0px 0px;
float: left;
}
.pagination {
float: right;
}
.pagination a {
color: black;
float: left;
padding: 8px 16px;
text-decoration: none;
transition: background-color .3s;
border: 1px solid #ddd;
margin: 0 4px;
}
.pagination a.active {
background-color: #4CAF50;
color: white;
border: 1px solid #4CAF50;
}
.pagination a:hover:not(.active) {
background-color: #ddd;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<table id="request-table">
</table>
</div>
<div class="clearfix">
<div class="box options">
<label>Requests Per Page: </label>
<select id="req_per_page" onchange="filter_requests()">
<option>5</option>
<option>10</option>
<option>ALL</option>
</select>
</div>
<div class="box pagination">
</div>
</div>
Below is the pagination logic as a function
function Pagination(pageEleArr, numOfEleToDisplayPerPage) {
this.pageEleArr = pageEleArr;
this.numOfEleToDisplayPerPage = numOfEleToDisplayPerPage;
this.elementCount = this.pageEleArr.length;
this.numOfPages = Math.ceil(this.elementCount / this.numOfEleToDisplayPerPage);
const pageElementsArr = function (arr, eleDispCount) {
const arrLen = arr.length;
const noOfPages = Math.ceil(arrLen / eleDispCount);
let pageArr = [];
let perPageArr = [];
let index = 0;
let condition = 0;
let remainingEleInArr = 0;
for (let i = 0; i < noOfPages; i++) {
if (i === 0) {
index = 0;
condition = eleDispCount;
}
for (let j = index; j < condition; j++) {
perPageArr.push(arr[j]);
}
pageArr.push(perPageArr);
if (i === 0) {
remainingEleInArr = arrLen - perPageArr.length;
} else {
remainingEleInArr = remainingEleInArr - perPageArr.length;
}
if (remainingEleInArr > 0) {
if (remainingEleInArr > eleDispCount) {
index = index + eleDispCount;
condition = condition + eleDispCount;
} else {
index = index + perPageArr.length;
condition = condition + remainingEleInArr;
}
}
perPageArr = [];
}
return pageArr;
}
this.display = function (pageNo) {
if (pageNo > this.numOfPages || pageNo <= 0) {
return -1;
} else {
console.log('Inside else loop in display method');
console.log(pageElementsArr(this.pageEleArr, this.numOfEleToDisplayPerPage));
console.log(pageElementsArr(this.pageEleArr, this.numOfEleToDisplayPerPage)[pageNo - 1]);
return pageElementsArr(this.pageEleArr, this.numOfEleToDisplayPerPage)[pageNo - 1];
}
}
}
const p1 = new Pagination(['a', 'b', 'c', 'd', 'e', 'f', 'g'], 3);
console.log(p1.elementCount);
console.log(p1.pageEleArr);
console.log(p1.numOfPages);
console.log(p1.numOfEleToDisplayPerPage);
console.log(p1.display(3));
This is the best one for me so far, it will include ´...´ at specific offset
function pages(current_page, last_page, onSides = 3) {
// pages
let pages = [];
// Loop through
for (let i = 1; i <= last_page; i++) {
// Define offset
let offset = (i == 1 || last_page) ? onSides + 1 : onSides;
// If added
if (i == 1 || (current_page - offset <= i && current_page + offset >= i) ||
i == current_page || i == last_page) {
pages.push(i);
} else if (i == current_page - (offset + 1) || i == current_page + (offset + 1)) {
pages.push('...');
}
}
return pages;
}
i am assuming you will display 10 data in every page
HTML:-
<!DOCTYPE html>
<html>
<head>
<title>pagination</title>
<link rel="stylesheet" href="pathofcssfile.css">
</head>
<body>
<div>
<table id="user"></table>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>
<li value="1">1</li>
<li value="2">2</li>
<li value="3">3</li>
<li value="4">4</li>
<li value="5">5</li>
<li value="6">6</li>
<li value="7">7</li>
<li value="8">8</li>
<li value="9">9</li>
<li value="10">10</li>
</ul>
<script src="pathnameofjsfile.js" type="text/javascript"></script>
</body>
</html>
JS:-
var xhr = new XMLHttpRequest();
xhr.open('GET',"https://jsonplaceholder.typicode.com/albums",true);
xhr.send();
var udata;
xhr.onload = function()
{
if(this.status == 200)
{
var userdata = JSON.parse(this.responseText);
console.log(userdata);
udata = userdata;
data(1);
}
}
$("li").click(function ()
{
var a = $(this).attr("value");
console.log("value li "+ a);
data(a);
});
function data(a)
{
var output = "";
for(i=((a-1)*10);i<(a*10);i++)
{
output +='<tr>'+
'<td>'+ udata[i].userId + '</td>'+
'<td>'+ udata[i].id + '</td>'+
'<td>'+ udata[i].title + '</td>'+ '<br>'
'</tr>';
}
document.getElementById('user').innerHTML = output;
}
CSS:-
ul{
display: flex;
list-style-type:none;
padding: 20px;
}
li{
padding: 20px;
}
td,tr{
padding: 10px;
}
Following is the Logic which accepts count from user and performs pagination in Javascript.
It prints alphabets. Hope it helps!!. Thankyou.
/*
*****
USER INPUT : NUMBER OF SUGGESTIONS.
*****
*/
var recordSize = prompt('please, enter the Record Size');
console.log(recordSize);
/*
*****
POPULATE SUGGESTIONS IN THE suggestion_set LIST.
*****
*/
var suggestion_set = [];
counter = 0;
asscicount = 65;
do{
if(asscicount <= 90){
var temp = String.fromCharCode(asscicount);
suggestion_set.push(temp);
asscicount += 1;
}else{
asscicount = 65;
var temp = String.fromCharCode(asscicount);
suggestion_set.push(temp);
asscicount += 1;
}
counter += 1;
}while(counter < recordSize);
console.log(suggestion_set);
/*
*****
LOGIC FOR PAGINATION
*****
*/
var totalRecords = recordSize, pageSize = 6;
var q = Math.floor(totalRecords/pageSize);
var r = totalRecords%pageSize;
var itr = 1;
if(r==0 ||r==1 ||r==2) {
itr=q;
}
else {
itr=q+1;
}
console.log(itr);
var output = "", pageCnt=1, newPage=false;
if(totalRecords <= pageSize+2) {
output += "\n";
for(var i=0; i < totalRecords; i++){
output += suggestion_set[i] + "\t";
}
}
else {
output += "\n";
for(var i=0; i<totalRecords; i++) {
//output += (i+1) + "\t";
if(pageCnt==1){
output += suggestion_set[i] + "\t";
if((i+1)==(pageSize+1)) {
output += "Next" + "\t";
pageCnt++;
newPage=true;
}
}
else {
if(newPage) {
output += "\n" + "Previous" + "\t";
newPage = false;
}
output += suggestion_set[i] + "\t";
if((i+1)==(pageSize*pageCnt+1) && (pageSize*pageCnt+1)<totalRecords) {
if((i+2) == (pageSize*pageCnt+2) && pageCnt==itr) {
output += (suggestion_set[i] + 1) + "\t";
break;
}
else {
output += "Next" + "\t";
pageCnt++;
newPage=true;
}
}
}
}
}
console.log(output);
file:icons.svg
<svg aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="icon-triangle-left" viewBox="0 0 20 20">
<title>triangle-left</title>
<path d="M14 5v10l-9-5 9-5z"></path>
</symbol>
<symbol id="icon-triangle-right" viewBox="0 0 20 20">
<title>triangle-right</title>
<path d="M15 10l-9 5v-10l9 5z"></path>
</symbol>
</defs>
</svg>
file: style.css
.results__btn--prev{
float: left;
flex-direction: row-reverse; }
.results__btn--next{
float: right; }
file index.html:
<body>
<form class="search">
<input type="text" class="search__field" placeholder="Search over 1,000,000 recipes...">
<button class="btn search__btn">
<svg class="search__icon">
<use href="img/icons.svg#icon-magnifying-glass"></use>
</svg>
<span>Search</span>
</button>
</form>
<div class="results">
<ul class="results__list">
</ul>
<div class="results__pages">
</div>
</div>
</body>
file: searchView.js
export const element = {
searchForm:document.querySelector('.search'),
searchInput: document.querySelector('.search__field'),
searchResultList: document.querySelector('.results__list'),
searchRes:document.querySelector('.results'),
searchResPages:document.querySelector('.results__pages')
}
export const getInput = () => element.searchInput.value;
export const clearResults = () =>{
element.searchResultList.innerHTML=``;
element.searchResPages.innerHTML=``;
}
export const clearInput = ()=> element.searchInput.value = "";
const limitRecipeTitle = (title, limit=17)=>{
const newTitle = [];
if(title.length>limit){
title.split(' ').reduce((acc, cur)=>{
if(acc+cur.length <= limit){
newTitle.push(cur);
}
return acc+cur.length;
},0);
}
return `${newTitle.join(' ')} ...`
}
const renderRecipe = recipe =>{
const markup = `
<li>
<a class="results__link" href="#${recipe.recipe_id}">
<figure class="results__fig">
<img src="${recipe.image_url}" alt="${limitRecipeTitle(recipe.title)}">
</figure>
<div class="results__data">
<h4 class="results__name">${recipe.title}</h4>
<p class="results__author">${recipe.publisher}</p>
</div>
</a>
</li>
`;
var htmlObject = document.createElement('div');
htmlObject.innerHTML = markup;
element.searchResultList.insertAdjacentElement('beforeend',htmlObject);
}
const createButton = (page, type)=>`
<button class="btn-inline results__btn--${type}" data-goto=${type === 'prev'? page-1 : page+1}>
<svg class="search__icon">
<use href="img/icons.svg#icon-triangle-${type === 'prev'? 'left' : 'right'}}"></use>
</svg>
<span>Page ${type === 'prev'? page-1 : page+1}</span>
</button>
`
const renderButtons = (page, numResults, resultPerPage)=>{
const pages = Math.ceil(numResults/resultPerPage);
let button;
if(page == 1 && pages >1){
//button to go to next page
button = createButton(page, 'next');
}else if(page<pages){
//both buttons
button = `
${createButton(page, 'prev')}
${createButton(page, 'next')}`;
}
else if (page === pages && pages > 1){
//Only button to go to prev page
button = createButton(page, 'prev');
}
element.searchResPages.insertAdjacentHTML('afterbegin', button);
}
export const renderResults = (recipes, page=1, resultPerPage=10) =>{
/*//recipes.foreach(el=>renderRecipe(el))
//or foreach will automatically call the render recipes
//recipes.forEach(renderRecipe)*/
const start = (page-1)*resultPerPage;
const end = page * resultPerPage;
recipes.slice(start, end).forEach(renderRecipe);
renderButtons(page, recipes.length, resultPerPage);
}
file: Search.js
export default class Search{
constructor(query){
this.query = query;
}
async getResults(){
try{
const res = await axios(`https://api.com/api/search?&q=${this.query}`);
this.result = res.data.recipes;
//console.log(this.result);
}catch(error){
alert(error);
}
}
}
file: Index.js
onst state = {};
const controlSearch = async()=>{
const query = searchView.getInput();
if (query){
state.search = new Search(query);
searchView.clearResults();
searchView.clearInput();
await state.search.getResults();
searchView.renderResults(state.search.result);
}
}
//event listner to the parent object to delegate the event
element.searchForm.addEventListener('submit', event=>{
console.log("submit search");
event.preventDefault();
controlSearch();
});
element.searchResPages.addEventListener('click', e=>{
const btn = e.target.closest('.btn-inline');
if(btn){
const goToPage = parseInt(btn.dataset.goto, 10);//base 10
searchView.clearResults();
searchView.renderResults(state.search.result, goToPage);
}
});
Just create and save a page token in global variable with window.nextPageToken. Send this to API server everytime you make a request and have it return the next one with response and you can easily keep track of last token. The below is an example how you can move forward and backward from search results. The key is the offset you send to API based on the nextPageToken that you have saved:
function getPrev() {
var offset = Number(window.nextPageToken) - limit * 2;
if (offset < 0) {
offset = 0;
}
window.nextPageToken = offset;
if (canSubmit(searchForm, offset)) {
searchForm.submit();
}
}
function getNext() {
var offset = Number(window.nextPageToken);
window.nextPageToken = offset;
if (canSubmit(searchForm, offset)) {
searchForm.submit();
}
}
var data = [1, 2, 3, 4, 5, 6, 7];
var item_per_page = 3;
var current_page = 1;
var pagination = {
total: data.length,
per_page: item_per_page,
current_page: current_page,
last_page: Math.ceil(data.length / item_per_page),
from: (current_page - 1) * item_per_page + 1,
to: current_page * item_per_page,
};
changePage();
function changePage() {
var temp = [];
for (let i = pagination.from; i <= pagination.to; i++) {
temp.push(data[i - 1]);
}
document.getElementById("result").innerHTML = temp.filter(x => x);
console.log(pagination);
}
function up() {
if (pagination.from == 1) {
return false;
}
pagination.current_page -= 1;
pagination.from = (pagination.current_page - 1) * item_per_page + 1;
pagination.to = pagination.current_page * item_per_page;
changePage();
}
function down() {
if (pagination.last_page == pagination.current_page) {
return false;
}
pagination.current_page += 1;
pagination.from = (pagination.current_page - 1) * item_per_page + 1;
pagination.to = pagination.current_page * item_per_page;
changePage();
}
console.log(pagination);
button {
width: 100px;
}
<div style="display: grid">
<button type="button" onclick="up()">Up</button>
<div id="result"></div>
<button type="button" onclick="down()">Down</button>
</div>
You can use the code from this minimal plugin.
https://www.npmjs.com/package/paginator-js
Array.prototype.paginate = function(pageNumber, itemsPerPage){
pageNumber = Number(pageNumber)
itemsPerPage = Number(itemsPerPage)
pageNumber = (pageNumber < 1 || isNaN(pageNumber)) ? 1 : pageNumber
itemsPerPage = (itemsPerPage < 1 || isNaN(itemsPerPage)) ? 1 : itemsPerPage
var start = ((pageNumber - 1) * itemsPerPage)
var end = start + itemsPerPage
var loopCount = 0
var result = {
data: [],
end: false
}
for(loopCount = start; loopCount < end; loopCount++){
this[loopCount] && result.data.push(this[loopCount]);
}
if(loopCount == this.length){
result.end = true
}
return result
}
I recently built a small quiz application, it currently only has two questions. After all the questions are finished I would like for the app to present a page that says "You made it here" (eventually I'll add more). However for some reason the final-function feedback of this code is not working. Where am I going wrong?
$(document).ready(function () {
var questions = [
{question: "Who is Zack Morris?",
choices: ['images/ACslater.jpg','images/CarltonBanks.jpeg','images/ZachMorris.jpg'],
quesNum: 1,
correctAns: 2},
{question: "Who is Corey Matthews?",
choices: ['images/CoryMatthews.jpeg','images/EdAlonzo.jpg','images/Shawnhunter.jpg'],
quesNum: 2,
correctAns: 1},
];
var userAnswer //THis needs to be looked into
var counter = 0;
var score = 0;
var html_string = '';
var string4end = ''
//function to loop choices in HTML, updates counter, checks answer
var update_html = function(currentQuestion) {
// put current question into a variable for convenience.
// put the question string between paragraph tags
html_string = '<p>' + currentQuestion.question + '</p>';
// create an unordered list for the choices
html_string += '<ul>';
// loop through the choices array
for (var j = 0; j < currentQuestion.choices.length; j++) {
// put the image as a list item
html_string += '<li><img src="' + currentQuestion.choices[j] + '"></li>';
}
html_string += '</ul>';
$('.setImg').html(html_string);
}
update_html(questions[0]);
$('.setImg li').on('click', function (e) {
userAnswer = $(this).index();
checkAnswer();
counter++;
update_html(questions[counter]);
$('#score').html(score);
showFinalFeedback();
});
//function to identify right question
function checkAnswer ()
{
if (userAnswer === questions[counter].correctAns)
{
score=+100;
}
}
function showFinalFeedback ()
{
if (counter === (questions.length+1))
{
string4end = '<p>' + 'You made it here!!!!' + '</p>';
$('.setImg').html(string4end);
}
}
});
I agree with Vector that you either should start with 1 as Counter initialization or, to check
if (counter < questions.length) {
return;
}
alert('You \'ve made it till here');
I also rewrote it in a form of a jquery plugin, maybe a handy comparison to your way of working?
jsfiddle: http://jsfiddle.net/DEb7J/
;(function($) {
function Question(options) {
if (typeof options === 'undefined') {
return;
}
this.chosen = -1;
this.question = options.question;
this.options = options.options;
this.correct = options.correct;
this.toString = function() {
var msg = '<h3><i>' + this.question + '</i></h3>';
for (var i = 0; i < this.options.length; i++) {
msg += '<a id="opt' + i + '" class="answer toggleOff" onclick="$(this.parentNode).data(\'quizMaster\').toggle(' + i + ')">' + this.options[i] + '</a>';
}
return msg;
};
this.toggle = function(i) {
var el = $('#opt' + i);
if ($(el).hasClass('toggleOff')) {
$(el).removeClass('toggleOff');
$(el).addClass('toggleOn');
} else {
$(el).removeClass('toggleOn');
$(el).addClass('toggleOff');
}
};
}
function Quiz(elem, options) {
this.element = $(elem);
this.lastQuestion = -1;
this.questions = [];
this.correct = 0;
if (typeof options !== 'undefined' && typeof options.questions !== undefined) {
for (var i = 0; i < options.questions.length; i++) {
this.questions.push(new Question(options.questions[i]));
}
}
this.start = function() {
this.lastQuestion = -1;
this.element.html('');
for (var i = 0; i < this.questions.length; i++) {
this.questions[i].chosen = -1;
}
this.correct = 0;
this.next();
};
this.next = function() {
if (this.lastQuestion >= 0) {
var p = this.questions[this.lastQuestion];
if (p.chosen === -1) {
alert('Answer the question first!');
return false;
}
if (p.chosen === p.correct) {
this.correct++;
}
$(this.element).html('');
}
this.lastQuestion++;
if (this.lastQuestion < this.questions.length) {
var q = this.questions[this.lastQuestion];
$(this.element).html(q.toString());
console.log(q.toString());
} else {
alert('you replied correct on ' + this.correct + ' out of ' + this.questions.length + ' questions');
this.start();
}
};
this.toggle = function(i) {
if (this.lastQuestion < this.questions.length) {
var q = this.questions[this.lastQuestion];
q.toggle(q.chosen);
q.toggle(i);
q.chosen = i;
}
};
}
$.fn.quizMaster = function(options) {
if (!this.length || typeof this.selector === 'undefined') {
return;
}
var quiz = new Quiz($(this), options);
quiz.start();
$(this).data('quizMaster', quiz);
$('#btnConfirmAnswer').on('click', function(e) {
e.preventDefault();
quiz.next();
});
};
}(jQuery));
$(function() {
$('#millionaire').quizMaster({
questions: [
{
question: 'Where are the everglades?',
options: ['Brazil','France','USA','South Africa'],
correct: 2
},
{
question: 'Witch sport uses the term "Homerun"?',
options: ['Basketball','Baseball','Hockey','American Football'],
correct: 1
}
]
});
});
Hey guys thanks for your help. I was able to use the following work around to ensure everything worked:
$('.setImg').on('click', 'li', function () {
userAnswer = $(this).index();
checkAnswer();
counter++;
$('#score').html(score);
if (counter < questions.length)
{
update_html(questions[counter]);
}
else{
showFinalFeedback();
}
});