Using API request to output MULTIPLE random JSON data to screen - javascript

Using the code below, I am able to retrieve user names from jsonplaceholder.com.
I am able to see ALL the user names using console.log, I cannot output ALL these items onscreen!
The output is only ONE of the array items.
Using userName[0], userName[1] outputs the same item?!
Using userName[0].textContent = info[1]; outputs the first letter of a user name.
Any help appreciated.
Thank you!
(function() {
// set api addresses
const usersJSON = "https://jsonplaceholder.typicode.com/users";
const commentsJSON = "https://jsonplaceholder.typicode.com/comments";
// user function //
// IIFE - get, parse, catch
(function getData() {
// get data
fetch(usersJSON)
.then(function(response) {
return response.json();
})
//parse to json
.then(function(data) {
// user name
for (let i = 0; i < data.length; i++) {
// generate random number 1 - 10
var num = Math.floor(Math.random() * 10);
displayName(data[num].name);
}
})
// display user name
function displayName(info) {
const userName = document.getElementsByClassName("userName");
for (let i = 0; i < userName.length; i++) {
userName[0].textContent = info;
userName[1].textContent = info;
}
}
})();
})();

The first thing you might want to do is use an ID, and grab the item using getElementById, then you can remove the loop to make the function simpler (unless you have multiple classes you want to append the names to)
Your issue is that you are using =, which overwrites the previously set text/data, which is why you are seeing one item. You are adding the first item from the array, then on the next loop iteration you replace it with the next item in the array.
Here are two different solutions to fix your problem:
Use += to append data instead of overwrite it:
function displayName(info) {
const userName = document.getElementById("users");
userName.innerHTML += '<p>' + info + '</p>';
}
Use appendChild to append data instead of overwrite it:
function displayName(info) {
const userName = document.getElementById("users")
const p = document.createElement('p')
p.textContent = info
userName.appendChild(p)
}
(function() {
// set api addresses
const usersJSON = "https://jsonplaceholder.typicode.com/users";
const commentsJSON = "https://jsonplaceholder.typicode.com/comments";
// user function //
// IIFE - get, parse, catch
(function getData() {
// get data
fetch(usersJSON)
.then(function(response) {
return response.json();
})
//parse to json
.then(function(data) {
// user name
for (let i = 0; i < data.length; i++) {
// generate random number 1 - 10
var num = Math.floor(Math.random() * 10);
displayName(data[num].name);
}
})
// display user name
function displayName(info) {
const userName = document.getElementById("users");
userName.innerHTML += '<p>' + info + '</p>';
}
})();
})();
<div id="users"></div>

Related

How can i solve this exercixe with String.prototype?

How can i create this to console log like this?
String.prototype.sheldonize = function () {
return `knock ${this}`
}
'Penny'.sheldonize(3)
I have this code at the moment, but I dont know how to repeat knock more times
Use the repeat method to establish a number of 'knocks' in the line and to establish how many times the line should repeat
String.prototype.sheldonize = function (repeats) {
const line = `${'knock '.repeat(repeats)}${this}, `.repeat(repeats)
return `${line.substring(0,line.length-2)}.`;
}
console.log('Penny'.sheldonize(3));
Using For Loop and repeat method
String.prototype.sheldonize = function(count) {
let ans = "";
for (let i = 0; i < count; i++) {
ans += "knock ";
}
ans = `${ans}${this}, `.repeat(count)
ans = ans.substring(0, ans.length - 2) + "."
return ans;
}
console.log('Penny'.sheldonize(3))
console.log('Penny'.sheldonize(2))
Create an array and on each iteration up to n - 1 add the string to it, finally joining it up and returning the string from the function.
// If you're adding to a prototype it's always best
// to double check to see if the method already exists
// no matter (in this case) how unlikely
if (!('sheldonize' in String.prototype)) {
String.prototype.sheldonize = function (n) {
// Create the array
const out = [];
// Create the string
const knock = 'knock '.repeat(n);
// Loop until `n - 1` has been reached
// pushing the string into the array
// on each iteration
for (let i = 0; i < n; i++) {
out.push(`${knock}${this}`);
}
// Finally return the joined array
return out.join(', ');
}
}
console.log('Penny'.sheldonize(3));
console.log('Penny'.sheldonize(2));
console.log('John'.sheldonize(4));
Additional documentation
repeat

I would like to know how I can make the "namePrinter" loop function work well?

I was trying to get javascript to print the result of the "generateName" function at least 10 times when I press a button in the html, so i tried a loop inside the function that generates the names and but it didn't work then I separated the loop and wrote it in the function "namePrinter" and create the global variable "names" to store the results of the function "generateName"
but I don't know what part of this whole process is wrong, I already reviewed other questions that were made in this forum but I didn't find an answer either
JS:
//this run the funtion that prints the names
document.getElementById("elvenFemButton").onclick = namePrinter;
//cutting characters function
function capFirst(string){
return string.charAt(10).toUpperCase() + string.slice(1);
}
//Randomizer
function getRandomInt (min,max){
return Math.floor(Math.random() * (max-min)) + min;
}
//this function generates names using both "elfFemName" and "elfLastName" and the functions from above
function generateName(){
var elfFemName1 = ["Adaia","Alisaie","Allisara","Alengwan","Alglaranna","Alachia","Alysia","Amberle","Anethra","Anwen","Apolline","Arathel","Ariane","Arianni","Ariel","Arwen","Ashalle","Ashniel","Atara","Ayara","Brelyna","Briala","Celebrían","Clothild","Cullich","Cylia","Dalish","Dirael","Eldyra","Elanor","Elenwen","Elezen","Ellia","Elynea","Éowyn","Failla","Faralda","Fleur","Freyalise","Galadriel","Gheyna","Jenassa","Katriel","Kira","Laina","Laniatte","Lauriel","Liallan","Liriel","Liselle","Loriel","Lorian","Lúthien","Máire","Mayael","Merril","Miara","Mihris","Minaeve","Nadja","Niranye","Nirya","Raewyn","Selveni","Sera","Shaera","Siofra","Taarie","Tauriel","Valora","Valya","Vanadis","Vanora","Velanna","Ylthin","Ysayle","Yvraine","Zelda"];
var elfLastName2 = ["Aearonian"," Agaraen","Agarher","Agarvran","Aire","Airendil","Amamion","Amdirthor","Amathal","Amather","Amathuilos","Amatheldir ","Amlugol","Aessereg","Aupwe","Calear","Caranagar","Cemno","Duindaer","Duirro","Eilianther","Gaer","Galadher","Gollor","Gulduron","Guldur","Guldurion","Hithaerben","Holiilo","Ingolmondur","Lar","Leucandil","Lanthir","Loeg","Lo","Lumorndaer","Morguldir","Morgulon","Naur","Neithaor","Nullion","Olchanar","Othanar","Olerydon","Ranchon","Rimdor","Rodor","Roher","Rhovanion","Rhovanion","Ruina","Russarocco","Sir","Sirdhemion","Tawaren","Tawarenion","Tawarher","Tordil","Uirchanar","Urendur","Urucher","Yr"];
var elfFemNameGenerator = capFirst(elfFemName1[getRandomInt(0, elfFemName1.length + 2)]) + " " + capFirst(elfLastName2[getRandomInt(0,elfLastName2.length +2)]);
return elfFemNameGenerator;
}
//i want this to get the result's from "generateName" and it should be a global value so i can use it in the next function
var names = generateName();
// this should print the name at least ten times but no
function namePrinter(){
var text = document.getElementById("textArea");
for (var i = 0; i < 10; i++) {
text[i].innerHTML(`${names}`)
}
return namePrinter;
}
innerHTML is not a function, it's a property. So, in the loop use text.innerHTML += name
However, if it's a <textarea> element, then you need to use value property instead:
//this run the funtion that prints the names
document.getElementById("elvenFemButton").onclick = namePrinter;
document.getElementById("elvenFemButton2").onclick = namePrinter2;
//cutting characters function
function capFirst(string){
return string.charAt(10).toUpperCase() + string.slice(1);
}
//Randomizer
function getRandomInt (min,max){
return Math.floor(Math.random() * (max-min)) + min;
}
//this function generates names using both "elfFemName" and "elfLastName" and the functions from above
function generateName(){
var elfFemName1 = ["Adaia","Alisaie","Allisara","Alengwan","Alglaranna","Alachia","Alysia","Amberle","Anethra","Anwen","Apolline","Arathel","Ariane","Arianni","Ariel","Arwen","Ashalle","Ashniel","Atara","Ayara","Brelyna","Briala","Celebrían","Clothild","Cullich","Cylia","Dalish","Dirael","Eldyra","Elanor","Elenwen","Elezen","Ellia","Elynea","Éowyn","Failla","Faralda","Fleur","Freyalise","Galadriel","Gheyna","Jenassa","Katriel","Kira","Laina","Laniatte","Lauriel","Liallan","Liriel","Liselle","Loriel","Lorian","Lúthien","Máire","Mayael","Merril","Miara","Mihris","Minaeve","Nadja","Niranye","Nirya","Raewyn","Selveni","Sera","Shaera","Siofra","Taarie","Tauriel","Valora","Valya","Vanadis","Vanora","Velanna","Ylthin","Ysayle","Yvraine","Zelda"];
var elfLastName2 = ["Aearonian"," Agaraen","Agarher","Agarvran","Aire","Airendil","Amamion","Amdirthor","Amathal","Amather","Amathuilos","Amatheldir ","Amlugol","Aessereg","Aupwe","Calear","Caranagar","Cemno","Duindaer","Duirro","Eilianther","Gaer","Galadher","Gollor","Gulduron","Guldur","Guldurion","Hithaerben","Holiilo","Ingolmondur","Lar","Leucandil","Lanthir","Loeg","Lo","Lumorndaer","Morguldir","Morgulon","Naur","Neithaor","Nullion","Olchanar","Othanar","Olerydon","Ranchon","Rimdor","Rodor","Roher","Rhovanion","Rhovanion","Ruina","Russarocco","Sir","Sirdhemion","Tawaren","Tawarenion","Tawarher","Tordil","Uirchanar","Urendur","Urucher","Yr"];
var elfFemNameGenerator = capFirst(elfFemName1[getRandomInt(0, elfFemName1.length)]) + " " + capFirst(elfLastName2[getRandomInt(0,elfLastName2.length)]);
return elfFemNameGenerator;
}
//i want this to get the result's from "generateName" and it should be a global value so i can use it in the next function
var names = generateName();
var names2 = [];
// this should print the name at least ten times but no
function namePrinter(){
var text = document.getElementById("textArea");
text.value = ""; //clear previous result
for (var i = 0; i < 10; i++) {
text.value += names;
}
}
function namePrinter2(){
var text = document.getElementById("textArea");
names2.length = 0; //clear array
for (var i = 0; i < 10; i++) {
names2[names2.length] = generateName();
}
text.value = names2;
}
<textarea id="textArea"></textarea>
<button id="elvenFemButton">generate names</button>
<button id="elvenFemButton2">generate different names</button>
This however as you can see will print the same name 10 times, if you need generate 10 names and store them globally, than you'll need save them in the array instead.
P.S.
Unrelated, but elfLastName2[getRandomInt(0,elfLastName2.length +2)] is wrong, you can't get value from an index that is larger than length of the array (aka +2 is wrong)

Arguments getting re-assigned

I am trying to strip out the display name from an email, e.g.
Steve<steve#steve.com> to steve#steve.com
function test1() {
var testemail = ["Steve<steve#steve.com>","displayname<display#steve.com>"];
var debug = stripEmail(testemail);
var debug9 = "";
}
function stripEmail(email) {
//Give me an email with a display name and I will strip out the display name
//"<Steve Gon> stevegon#google.com"
if (typeof email === 'string') {
var arr = [email];
} else {
var arr = email;
}
for (i=0; i<arr.length; i++) {
if (arr[i].search("<")>-1) {//If there is no less than, then it doesn't have a display name
var part1 = arr[i].split("<");
if (part1.length == 2) {
arr[i] = part1[1].replace(">","");
arr[i] = arr[i].replace("<","");
arr[i] = arr[i].replace(" ","");
}
}
}
return arr;
}
Once the code steps out of stripEmail, the argument email is changed to the result. I've notice this happening in some other functions as well. This is resulting in strange problems when I try to use the variables.
Variable testemail set:
Once I step over the function, testemail is changed.
Avoid setting one array equal to another array if you want to avoid changing the original array. Instead of reusing the email variable, create a new output variable. In the code below, the emails are put into a new array named result.
The stripEmail function handles both a string and an array, and always returns an array that is different than the source array, leaving the original array unchanged.
The code can be changed to:
function test1() {
var testemail = ["Steve<steve#steve.com>","displayname<display#steve.com>"];
Logger.log('testemail: ' + testemail)
var debug = stripEmail(testemail);
Logger.log('debug: ' + debug)
Logger.log('testemail: ' + testemail)
}
function stripEmail(email) {
var arr,i,part1,result;
result = [];
//Give me an email with a display name and I will strip out the display name
//"<Steve Gon> stevegon#google.com"
if (typeof email === 'string') {
email = email.split(",");
}
for (i=0; i<email.length; i++) {
if (email[i].search("<")>-1) {//If there is no less than, then it doesn't have a display name
part1 = email[i].split("<");
if (part1.length == 2) {
result[i] = part1[1].replace(">","");
result[i] = result[i].replace("<","");
result[i] = result[i].replace(" ","");
}
}
}
return result;
}

AngularFire: $add sets fbUID and custom UID, why?

Before there are any questions, I have a function that creates a custom UID because I don't "need" the long Firebase UID and wanted something shorter which is more easy to remember.
Anyway, in my create-function I'm not sure I'm adding it to the db correctly.
Here's a snippet and below that is how it looks in my database.
$scope.create = function(){
// Generate a shorter random uid (6 chars) that replaces the long regular Firebase uid
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
uid_length = 6;
generator = function(){
random = '';
for(var i = 0; i < uid_length; i++){
random += letters.charAt(Math.floor(Math.random() * letters.length));
}
return random;
}
generator();
var lists = new Firebase('https://url.firebaseio.com/lists/' + random);
firebaseLists = $firebaseArray(lists);
//lists.child(random).set(random);
firebaseLists.$add(random).then(function(lists){
})
This gives me, for example:
lists
0Knn8M <- custom UID
-KH6kSxPAaerjU: '0Knn8M'
As I want the things that are added to 0Knn8M displayed on my page, it also displays the FB UID. Of course I could do a CSS 'display:none;' on that child but shouldn't it be another way around it?
I think, that here is an error:
generator = function(){
random = '';
for(var i = 0; i < uid_length; i++){
random += letters.charAt(Math.floor(Math.random() * letters.length));
}
return random;
}
generator();
var lists = new Firebase('https://url.firebaseio.com/lists/' + random);
You are calling generator() but not assigning it result to any variable. In var lists = new Firebase('https://url.firebaseio.com/lists/' + random); the variable random is now undefined. So firebase generates it's own id I guess.
So you need to change just one thing var random = generator().

String in array showing up as undefined, despite being console.log-ed successfully a few lines earlier

In the for loop below, when I console.log searchTermsList[i] the first time (console.log('searchTermsList[i] is:' + searchTermsList[i]);), it works correctly and prints out the respective string.
However, when I do it again later in the code (console.log('the searchTermsList[i] Im about to use for the query is:' + searchTermsList[i]);), it prints out that it's undefined. Both console.logs are within the same loop, so why isn't the 2nd one able to find the value?
for (var i = 0; (i < top3List.length) && (i < searchTermsList.length); i++){
console.log('searchTermsList[i] is:' + searchTermsList[i]);
console.log('top3List[i] is:' + top3List[i]);
var MCI_Results = Parse.Object.extend("MCI_Results");
var MCI_Results_Comparison_Query = new Parse.Query(MCI_Results);
// Compare respective items' MCI_Results array to eBay results (top3List[i])
MCI_Results_Comparison_Query.equalTo('parent', user);
MCI_Results_Comparison_Query.contains('searchTerm', searchTermsList[i]);
MCI_Results_Comparison_Query.containsAll('Results', top3List[i]);
MCI_Results_Comparison_Query.find()
.then(function(results) {
// No new items, Results and top3List[i] are identical
if (results.length > 0) {
console.log('done updating channel');
}
// New items found, Results and top3List[i] don't match.
else {
console.log('no matching MCI_Results, lets push some new shit');
// Find MCI_Results object for specific item
var MCI_Results_Update_Query = new Parse.Query(MCI_Results);
MCI_Results_Update_Query.equalTo('parent', user);
console.log('the searchTermsList[i] Im about to use for the query is:' + searchTermsList[i]);
MCI_Results_Update_Query.contains('searchTerm', searchTermsList[i]);
// Update MCI_Results with new top3List eBay results
MCI_Results_Update_Query.find()
.then(function(results) {
console.log('totally just updated the MCI_Results, NBD');
})
.then(function() {
// Check for high priority MC items
});
}
});
}
i is a mutable variable. i++ will change i to point to a different index by the time that function is called.
You'll need to create a new variable in a new scope, possibly using an immediately-invoked anonymous function, and not change it.
An example:
var makeBadAdders = function(n) {
var adders = []
for (var i = 0; i < n; i++)
adders[i] = function(x) {
// Closes over a mutable variable.
// Function will use the most up-to-date value of i.
return i + x;
}
return adders
}
var badAdders = makeBadAdders(3);
console.log(badAdders[1](1)); // 4
console.log(badAdders[2](1)); // Also 4
var makeAdders = function(n) {
var adders = []
for (var i = 0; i < n; i++)
adders[i] = makeAdder(i);
return adders
}
var makeAdder = function(i) {
// Closes over an effectively immutable variable (i).
return function(x) {
return x + i;
}
}
var goodAdders = makeAdders(3);
console.log(goodAdders[1](1)); // 2
Note that you could write makeAdder inline like so:
adders[i] = (function(i) {
return x + i
})(i)
(This shadows the outer, mutable i.)
But usually, it's better to just avoid mutable variables and use something like forEach instead. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)

Categories

Resources