Typescript pagination - arrays

I am trying to create a pagination functionality for an Angular project and I have to do this only with typescript.
Task: paginate an array, number of objects displayed per page is 15.
My declarations are:
PAGE_SIZE: number = 15;
total: number = this.booksArray.length;
pageNumber: number = 1;
pageBooks!: BookModel[];
numberOfPages: number = Math.ceil(this.total/this.PAGE_SIZE);
currentPage!: number;
Total will be the number of the objects within the array, pageNumber is initialized to 1.
pageBooks should be a subarray of the booksArray, and it is the array to be displayed on the page.
Getting the books to display on the page is done through the following method, however if I use the pageBooks variable in the *ngFor html it won't yield anything; instead I use the full method name and arg.(1st problem)
getPageBooks(pageNumber: number) {
var trimLeft: any = (pageNumber - 1) * this.PAGE_SIZE;
var trimRight: any = pageNumber * this.PAGE_SIZE;
(trimRight < this.booksArray[this.total - 1]) ? pageNumber * this.PAGE_SIZE : this.booksArray[(this.total - 1)];
const pageBooks = this.booksArray.slice(trimLeft, trimRight);
return pageBooks;
}
Console logging in the ngOnInit() returns an undefined or 0, which halts my progress(2nd problem).
I have also prepared several methods to add to my html as pagination events:
showPage(index) {
let displayedPage = this.getPageBooks(index);
this.displayBooks(displayedPage);
this.currentPage = index;
}
showFirstPage() {
this.showPage(1);
}
showLastPage() {
this.showPage(numberOfPages);
}
showNextPage() {
let pageToDisplay = this.currentPage + 1;
this.currentPage = pageToDisplay;
this.showPage(this.currentPage);
}
showPreviousPage() {
let pageToDisplay = this.currentPage - 1;
this.currentPage = pageToDisplay;
this.showPage(this.currentPage);
}
Could someone please help and advise on what I am doing wrong?
Thanks!

Related

Is it possible to show gradients with react-svgmt?

I would like to use react-svgmt to manipulate SVG's. These SVG's can be uploaded from the users. My problem is, that if the SVG has a gradient these parts of the SVG are not shown.
Has anybody a solution for my problem to reactivate these links after the import of the SVG via react-svgmt?
With the developertools of my browser I was be able the see that the elements are in the code, but the grandients will be linked to the elements and these links are broken.
I have seen that other people has the same problem with gradients and created an issue on github, but the developer did not respond.
I found a solution for my problem.
react-svgmt add to elements like linearGradients "-{nr}" to its id-names. Then this fill:url(#linear-gradient-2); does not work anymore in the style-tags, because it must be fill:url(#linear-gradient-2-{nr});.
So the first SVGProxy after loading is <SvgProxy selector="linearGradient" onElementSelected={handleGradients} ></ SvgProxy>
an the function handleGradients looks like following and saves the {nr}
const handleGradients = (gradients) => { if (typeof gradients.length !== 'undefined') { const output = gradients.map((g, i) => { nr = g.id.substring(g.id.lastIndexOf("-")+1); setNr(g.id.substring(g.id.lastIndexOf("-")+1)); if(g.href.baseVal.length > 0) { var base = g.href.baseVal; g.href.baseVal = base + '-' + nr; } return g; }); } else { nr = gradients.id.substring(gradients.id.lastIndexOf("-")+1); setNr(gradients.id.substring(gradients.id.lastIndexOf("-")+1)); if(gradients.href.baseVal.length > 0) { var base = gradients.href.baseVal; gradients.href.baseVal = base + '-' + nr; } } };
Then I had another SVGProxy
<SvgProxy selector="defs > style" onElementSelected={handleStyleElem} ></ SvgProxy>
with the following handlefunction which replaces all urls with the schema from above
const handleStyleElem = (svgStyle) => { var styleStr = svgStyle.outerHTML; styleStr = styleStr.replaceAll(/url\(#((\w|-)*)\);/g, 'url(#$1-'+ nr +');'); svgStyle.outerHTML = styleStr; };

Getting the sum for all of the object retrieve from SharePoint API

.subscribe((dataTotal) => {
console.log(dataTotal)
this.toGetHourData=dataTotal;
const AssociateArray = []
AssociateArray.push({dataTotal : Number})
let associateSum: number = 0;
AssociateArray.forEach(a => associateSum += a.value);
console.log(associateSum);
},
This is my code. I have pushed all of the object into an array. but when i try to sum it up. the console log a NaN.
p.s: this is my first time with stackoverflow
There are a number of issues in your code
1. Incorrect type declaration
You have declared dataTotal : Number For types you need to use number not Number hence dataTotal : number
2. You are adding a type to an array!
Consider the code AssociateArray.push({dataTotal : Number}). {dataTotal : Number} is basically a type so you are pushing an empty type to the array...
3. You can use other means to sum e.g using reduce
With these in mind you can change your code to
.subscribe((dataTotal) => {
this.toGetHourData = dataTotal;
let associateSum: number = dataTotal.reduce((prev, next) => prev + next.value , 0);
console.log(associateSum);
}
.subscribe((dataTotal) => {
console.log(dataTotal)
this.toGetHourData=dataTotal;
var clean = []
var totalnum = 0;
var associateArray = dataTotal
associateArray.forEach(element => {
if (element.strTotalAssociates !== NaN) {
clean.push(element)
console.log(element)
totalnum += element.strTotalAssociates;
console.log(totalnum)
}
});
this is the answer that me and my colleague came up with and its work.

I'm trying to randomize 5 selections from a list of people

This might be less difficult than I'm making it out to be, but I'm trying to make a Discord.JS bot command, that will take however many arguments I have. For example: !randomize 1,2,3,4,5,6,7,8,9,10
And the bot would respond with something like: "I have chosen: 4,2,7,3,9!" Any help?
Current attempt: Not exactly sure what I'm doing.
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}`
`bot.on('message', async msg => {
if(msg.content === "!add") {
//message.member.user.tag
var msgArray = msg.content.split(" ");
var args = msgArray.slice(1);
var user = args[1];
//if(!args[1]) return msg.channel.send("Please specify an argument!");
if(nameList.includes(user)) {
msg.reply("You're already on the list.")
} else {
nameList.push(args[1]);
msg.channel.send(`${args[1]} has been added to the list!\n Current List:` + nameList);
}
}
if(msg.content === "!bonus") {
if(nameList.length === 0) {
msg.reply("Either the list is empty, or I'm not in the mood!");
} else {
shuffleArray(nameList);
var chosenOne = nameList.pop();
nameList = [];
msg.reply(chosenOne + ' has been chosen! Good luck!');
}
}
if(msg.content === "!list") {
if(nameList.length === 0) {
msg.channel.send("Either the list is empty, or I'm not in the mood!");
} else {
msg.channel.send('The current list:' + nameList);
}
});```
Here's some simple steps to select 5 random elements from an array...
Construct an array of possible selections. In this example I've used names for the first 10 letters of the alphabet. In your code, it'll be the command arguments or predefined nameList.
Make a new array to hold the elements picked.
At some point before #3, you should check to make sure the pool the user has provided is large enough to make 5 selections (Array.length).
Use a for loop to execute the next code multiple times.
Generate a random number representing the index of a selected element (Math.random(), Math.floor()/double NOT bitwise operator).
Push the selection into the array.
Remove the chosen element from the original pool (Array.splice()).
Return the results.
const pool = ['Albert', 'Bob', 'Charlie', 'David', 'Edward', 'Francis', 'George', 'Horacio', 'Ivan', 'Jim'];
const selected = [];
for (let i = 0; i < 5; i++) {
const num = ~~(Math.random() * pool.length);
selected.push(pool[num]);
pool.splice(num, 1);
}
console.log(`I have chosen: ${selected.join(', ')}`);
Take this example and manipulate it within your code to suit your purpose.

How to sort a VueJS object in descending order of the number of occurrences?

I have a dynamic object that consists of the number of occurrences from a user selection. The object looks like this:
{ "Excitement": 2, "Competence": 3, "Sophistication": 1 }
This is the function:
rankFactors() {
const headers = this.headers;
var counts = {};
for (var i = 0; i < headers.length; i++) {
var num = headers[i];
counts[num] = counts[num] ? counts[num] + 1 : 1;
}
return counts;
}
How do I sort this object so that it is always in descending order? That way I can print it as a 'Top 3' list.
This is my CodeSandbox: https://codesandbox.io/embed/vue-template-mzi03
To reproduce just make selection of personality traits, with multiple options from a few headers.
I think I'd do it something like this:
rankFactors() {
const headers = this.headers;
const counts = {};
for (const header of headers) {
counts[header] = (counts[header] || 0) + 1;
}
const factors = Object.keys(counts).map(header => {
return {
name: header,
count: counts[header]
}
});
factors.sort((a, b) => b.count - a.count);
return factors;
}
The first stage is very similar to what you had, building up an object of counts. That's an easy data structure to work with for gathering those counts but once that stage is done it's not a great choice for dealing with sorting. For that we're better off with an array.
So next up it converts the object into an array of objects, each of the form {name: 'Excitement', count: 2}. This array is then sorted based on the counts and then returned. You could throw in a .slice(0, 3) if you just want the top 3.

Add cookie / no-repeat function to random page refresh

I have been using this java code to call a random html page from a list of 49 on a set timer (or upon page refresh). I would like to convert it so that a cookie - or something else - saves the pages that have already been shown so that upon refresh the user always receives a new page, until the list is finished, at which point the cookie is emptied/deleted.
I found this code for a cookie image array. Could I use it with this? A variant of this also appears here. Apologies, my coding is pretty poor. Any advice appreciated:
<script type="text/javascript">
var sites = [
"name1.html",
"name2.html",
"name3.html",
"name...etc.html",
"name49.html",
]
$(document).ready(function() {
newPage();
});
function newPage()
{
setTimeout(newPage, 60000);
var min = 0;
var max = 48;
var num = Math.floor(Math.random() * (max - min + 1)) + min;
$('#target').attr('src',sites[num]);
}
</script>
var numSites = 49;
var seen = new Array(numSites);
$(document).ready(function() {
var cookie = unescape(getCookie("seen"));
seen = cookie ? cookie.split(',') : seen;
setTimeout(gotoNext, 60000);
});
function gotoNext() {
var num = getRandom();
var count = 0;
while (seen[num] == 1) {
num++;
if (num >= numSites) {
num = 0;
count++;
if (count > 1) {
resetSeen();
num = getRandom();
}
}
}
seen[num] = 1;
setCookie("seen", escape(seen.join(',')), 365);
window.location = "name" + num + ".html";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name)==0) return c.substring(name.length, c.length);
}
return "";
}
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires;
}
function resetSeen() {
for (var i=0; i<numSites; i++) {
seen[i] = "";
}
}
function getRandom() {
return Math.ceil(Math.random() * numSites);
}
It looks like you're using jQuery so I'll recommend using a jquery plugin for managing cookies much more neatly.
Copy & paste the contents of this URL to a new js file on your server and include it after the jquery file: https://raw.githubusercontent.com/carhartl/jquery-cookie/master/jquery.cookie.js
Or you could possibly use the get/set cookie functions from the other answer you mention.
The main thing to remember is that the cookie is stored as a string so you'll be join()ing and split()ing the array.
The other thing to note is that because we want a random item from the items we haven't visited yet it's more efficient to keep track of those rather than the ones we have visited.
What this means is we always choose a random item from what's left instead of looping over everything and checking each time if we've been there already as that would get very inefficient.
var sites = [ 'name1.html', 'name2.html', 'name3.html', ...etc... ],
unvisited = sites.slice(0); // .slice(0) clones the array
// if the cookie has a value then make it into the unvisited array
if ( $.cookie( 'unvisited' ) )
unvisited = $.cookie( 'unvisited' ).split( ',' );
$(document).ready(function() {
newPage();
});
function newPage() {
setTimeout( newPage, 60000 );
// check if the unvisited array needs resetting
if ( unvisited.length == 0 ) {
unvisited = sites.slice(0);
$.removeCookie( 'unvisited' );
}
// get a new index from the unvisited array
var num = Math.floor( Math.random() * unvisited.length );
// remove the item from the array and save the cookie
var site = unvisited.splice( num, 1 )[ 0 ];
// save the unvisited array minus the site we just spliced out
$.cookie( 'unvisited', unvisited.join( ',' ) );
$( '#target' ).attr( 'src', site );
}

Resources