I am trying to build a Calculator where you can Pick different Cryptocurrencies and build a Portfolio for Testing and Tracking. I choose Coingecko API v3 for this and use Fetch to do the API Calls. https://www.coingecko.com/en/api
The API Calls are working and I get JSON Data from the Server. I built a Function that is delivering the Top 100 Coins, putting them into a Datalist-Tag for Choosing from an Input:
function fetch_coinlist(url) {
fetch(url)
.then(function(response) {
if (response.status !== 200) {
alert("Can Not get Price Api! Status: " + response.status);
return;
}
response.json().then(function(data) {
document.getElementById("coinlist").innerHTML = "";
for (i = 0; i <= 99; i++) {
const toplist = document.createElement("option");
toplist.id = data[i].symbol;
toplist.innerHTML =
data[i].symbol.toUpperCase() + " - " + data[i].name;
document.getElementById("coinlisting").appendChild(toplist);
//console.log(data[i].id);
//console.log(data[i].name);
//console.log(data[i].symbol);
//console.log(data[i].image);
//console.log(data[i].current_price);
}
});
})
.catch(function(err) {
alert("Can Not get Price Api! Status: " + err);
});
}
<input list="coinlisting" id="coinlist" name="coinlist" class="curser-choose" />
<datalist id="coinlisting" placeholder="Choose Coin"></datalist>
This is working, I am using a For loop to go through the response. I try to Display the Price for a Coin if the User picked one Option from this Datalist and for further functionality I think it would be best that I could call an object like data.coinname.current_price so I can build a Function where i could pass a string to it and get the price for that coin.
However, right now I would have to use data[0].current_price for the current Price of the first item in the list. The items on the called List can Change over time, so I can not make a static assignment, I think I could do this each time I call the API but it would not benefit my target to have a function that I can feed with a name as a string to do the Price Call.
It is possible to get the Price in the same call as the list but I can not figure out how I would be able to do what I have in mind with that. On the site for the API are different calls listed, one of the first is the /coins/list call and it says "Use this to obtain all the coins’ id in order to make API calls" and gives a JSON object for each available coin like:
{
"id": "1inch",
"symbol": "1inch",
"name": "1inch"
}
Do I need to do this call first in order to achieve what I have in mind? But I'm unsure how that would help me get the solution I am looking for... I am struggling to find a solution for this and feel stuck, I feel like I don't understand it properly and it should be not as hard as I think it is right now :D If you have an idea of how to accomplish this please let me know!
You could do something like this. I kept the html simple.
fetch_coinlist: fetches a coin list. After fetching the coins list it converts the result to an object instead of a list. Each coin can be accessed using coins["<coin id>"].
show_coinlist does the visualisation
addEventListener catches when you select an item.
const gecko = "https://api.coingecko.com/api/v3/";
var coins = {};
// selector actions
const selector = document.querySelector('#coinlisting');
const info = document.querySelector('#info');
selector.addEventListener('change', event => {
info.innerHTML = "Selected item: " + selector.value + " : " + coins[selector.value].name;
});
function fetch_coinlist() {
fetch(gecko + "coins/list")
.then(function(response) {
if (response.status !== 200) {
alert("Can Not get List Api! Status: " + response.status);
return;
}
response.json().then(function(data) {
coins = {};
for (let i = 0, l = data.length; i < l; i++) {
let {id, ...info} = data[i];
coins[id] = info;
}
show_coinlist();
});
})
.catch(function(err) {
alert("Can Not get Price Api! Status: " + err);
});
}
function show_coinlist(){
for (let id in coins) {
let item = coins[id];
const toplist = document.createElement("option");
toplist.value = id;
toplist.innerHTML = item.symbol.toUpperCase() + " - " + item.name;
document.getElementById("coinlisting").appendChild(toplist);
}
}
fetch_coinlist();
<select id="coinlisting" placeholder="Choose Coin"></select>
<div id="info"></div>
Related
I'm trying to get the groups a given user (typed into a textbox in page) is a member of. Haven't had much success so decided to get all the groups, iterate through their users to find the groups the user is a part of. Tried the following but can't find a way to iterate through the users.
what am I missing? is there a better way to achieve my main goal?
var oGroupCollection, clientContext, loadedGroup, oUserCollection, oUser ;
function GetAllSiteGroups() {
// You can optionally specify the Site URL here to get the context
// If you don't specify the URL, the method will get the context of the current site
var clientContext = new SP.ClientContext("http://MyServer/sites/SiteCollection");
// Get Site Group Collection object
oGroupCollection = clientContext.get_web().get_siteGroups();
//oUserCollection = oGroupCollection.getByTitle('sp_red_dehn_zigaretten').get_users();
//console.log(oUserCollection);
// Load Site groups
clientContext.load(oGroupCollection);
// Execute the query to the server.
clientContext.executeQueryAsync(onsuccess, onfailed);
}
function onsuccess() {
// Iterate through each item
var oEnumerator = oGroupCollection.getEnumerator();
while (oEnumerator.moveNext()) {
var oGroup = oEnumerator.get_current();
console.log(oGroup);
console.log("Title of the group is: " + oGroup.get_title() + "\n");
oUserCollection = oGroup.get_users();
console.log(oUserCollection);
clientContext.load(oUserCollection);
clientContext.executeQueryAsync(onsuccess2, onfailed);
}
}
function onfailed(sender, args) {
console.log('Failed' + args.get_message() + '\n' + args.get_stackTrace());
}
function onsuccess2() {
// Iterate through each item
var oEnumerator = oUserCollection.getEnumerator();
while (oEnumerator.moveNext()) {
oUser = oEnumerator.get_current();
console.log(oUser);
//console.log("Title of the group is: " + oUser.get_title() + "\n");
}
}
I am using MongoDB and Node.JS, I am trying to get data out of my MongoDB and show into my html page which I have working with the below code however this just brings back ALL entries in no particular order:
server.js
// This is for getting the list of all players from my DB
app.get("/getPlayers", function(request, response) {
db.getPlayers().then(function(players){
console.log(players);
response.send(players);
});
});
leadership.html
<script>
$(function() {
$.get("http://localhost:9000/getPlayers", {}, function (res) {
let data = res;
console.log(res);
for (i = 0; i < data.length; i++) {
let name = data[i].name;
let score = data[i].score;
console.log(data[i].name);
$("#leadership").append("<tr><td class=\"name\">"
+ data[i].name + "</td><td class=\"score\">"
+ data[i].score + "</td></tr>");
}
});
});
</script>
After looking at W3 Schools I tried to alter the code to this:
db.getPlayers().sort().limit(10).then(function(players)
However my Chrome console brings back an internal server error 500. Can someone point out how I can sort by LARGEST NUMBER first, then LIMIT the results to say 10? Within the database there is a collection called players, which holds name and score
db.js
var Player = mongoose.model("Player", {name: String, score: Number});
module.exports.Player = Player;
Try something like this.
Order, sort and limit can be passed from front end or change default values after : mark.
Players is imported model, you can do it this way or use method in the model itself.
app.post('/api/players',(req,res)=>{
let order = req.body.order ? req.body.order : "-1";
let sortBy = req.body.sortBy ? req.body.sortBy : "_id";
let limit = req.body.limit ? parseInt(req.body.limit) : 100;
Players.
find().
sort([[sortBy,order]]).
limit(limit).
exec((err,players)=>{
if(err) return res.status(400).send(err);
res.status(200).json({
size: players.length,
players
})
})
})
I'm trying to let users favorite a project. I'm storing these projects at 2 places so I have to update them simultaneously. After looking at the firebase docs, using transactions seemed to be the best option.
.
Function to toggle the favorite status:
function toggleFavorite (projectReference, uid) {
projectReference.transaction(function(project) {
console.log('Before-Favorites :' + project.favoriteCount);
if (project.favorites && project.favorites[uid]) {
project.favoriteCount--;
project.favorites[uid] = null;
} else {
project.favoriteCount++;
if(!project.favorites) {
project.favorites= {};
}
project.favorites[uid] = true;
}
console.log(' After-Favorites :' + project.favoriteCount);
return project;
});
};
Function to add the eventListeners to the projects:
function AddToFavorite (uid, authorId) {
const favoriteList = document.querySelectorAll('.btnFavorite');
for(var i = 0; i<favoriteList.length; i++) {
favoriteList[i].addEventListener('click', function(event) {
const projectId = this.dataset.id;
console.log(projectId);
const globalProjectRef = firebase.database().ref('/projects/' + projectId);
const userProjectRef = firebase.database().ref('/user-projects/' + authorId + '/' + projectId);
toggleFavorite(globalProjectRef,uid);
toggleFavorite(userProjectRef,uid);
});
}
}
I want to store the uid of the current user under a 'favorites' node within the project location.
When i want to store the data I can see it appearing in the database but removing it after instantly. Followed by that i get an error in the console that my project object is null.
What's the best way of solving this issue ?
I want to fetch the https://swapi.co/api/people/ all name and other detail but when I am using an axios call to get the data and I am getting undefined for all data but if want one name I am getting a CORS error in console.
let button = document.querySelector("#button");
let name = document.querySelector("#displayDetail");
function getDetail(){
var apiURL="https://swapi.co/api/people";
axios.get(apiURL).then(function(response){
showDetail(response.data);
});
}
function showDetail(data){
name.innerText=data.name;
}
button.addEventListener('click',getDetail);
The JSON data from https://swapi.co/api/people doesn’t have a name member. Instead it has a results member that is an array of objects, each of which has a name member.
So you need to loop through that data.results array to get each name:
function getDetail() {
var apiURL = "https://swapi.co/api/people";
axios.get(apiURL).then(function(response) {
showDetail(response.data);
});
}
function showDetail(data) {
for (i = 0; i < data.results.length; i++) {
console.log(data.results[i].name);
}
}
getDetail();
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
But note: That API endpoint paginates the results; so to get all the names, check data.next to get the URL for the next page, then make a new request with that URL to get the next set of results:
function getDetail(apiURL) {
axios.get(apiURL).then(function(response) {
showDetail(response.data);
});
}
function showDetail(data) {
for (i = 0; i < data.results.length; i++) {
names = names + data.results[i].name + "\n";
// name1.innerText = name1.innerText + "\n" + data.results[i].name;
}
if (data.next) {
getDetail(data.next);
} else {
console.log(names); // name1.innerText = names;
}
}
var names = "";
getDetail("https://swapi.co/api/people");
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
try with this
swapi.co/api/people/
change for
swapi.dev/api/people/
All resources support a search parameter that filters the set of resources returned. This allows you to make queries like:
https://swapi.co/api/people/?search=r2d2
To see the set of search fields for each resource, check out the individual resource documentation.
New to javascript here, so callbacks are still a little iffy in my brain.
What I'm trying to do is: given a "menu" which is an array of objectId's, query for each foodItem that corresponds to that objectId, get its votes, put it in a min-heap (to determine which are the top 5 items), and return those top 5 items.
My heap at the end is empty because I realize that JavaScript is asynchronous and that when I try to get the heap data, the callback might not have necessarily completed.
If it were just one call, I would just nest the callbacks, but since this is a loop I'm not really sure what to do.
function getTopFoods(menu, heap, callback) {
//go through each objectId, get its foodItem and then its votes, then heap it
console.log("got to TopFoods");
for (var i = 0; i < menu.length; i++) {
var foodID = menu[i];
var FoodItem = Parse.Object.extend("FoodItem");
var foodQuery = new Parse.Query(FoodItem);
foodQuery.equalTo("objectId", foodID);
//get corresponding foodItem
foodQuery.find({
success: function(foodResult) {
//got specific food Item
var votes = foodResult.get("votes");
console.log("votes: " + votes);
if (heap.length < 5) {
heap.queue(foodResult);
} else {
if (votes > heap.peek().get("votes")) {
heap.dequeue();
heap.queue(foodResult);
}
}
},
error: function(error) {
console.log("Food error: " + error.code + " " + error.message);
}
});
}
var topFoods = [];
for (var i = 0; i < 5; i++) {
topFoods[i] = heap.dequeue();
}
callback(topFoods);
}
The easiest way is to use promises; at this stage, this involves using a library (coming to JavaScript proper in ES6). If you want a low-tech solution, just count stuff:
var waitingCount = menu.length;
for (....) {
...
success: function(foodResult) {
...
if (!--waitingCount) {
callback(topFive(heap));
}
},
error: function(error) {
--waitingCount;
...
}
...
}
This is just the basic idea. It would be good if you also decremented the counter on failed responses, since this way a single fail will leave you hanging.
EDIT: Err, obviously, the check needs to go to the bottom of success, not to the top as my snippet indicated before, or you'll miss the last element. I also put in the error case.
EDIT2: As eth3lbert notes, parse.com API also supports promises (I don't work with parse.com, so... thanks for the tip). In that case, here's what you do:
var promises = [];
for (....) {
var promise = foodQuery.find({
...
});
promises.push(promise);
});
Parse.Promise.when(promises).then(function()) {
callback(topFive(heap));
}