I'm doing a request to a website for a game; the game is League of Legens if any of you are familiar with it but it doesn't matter.
I want to pull some data to get the name of a champion, the thing is that Riot (The API's provider) gives an endpoint to get some points of each champion and the ID so I have to make a request to another website to get the name of the champion but since that second website doesn't have the data that I am looking for (which are the points). I can't use just that data.
Anyway, the problem that I am facing is that I already have the Id's from the champs that are shown on the person's profile, which are 3. With the second request I want to compare the id of all champs and if it find the same id of the 3 champs requested before it displays the name of only those 3 champs. I'm using the request package to do this on Node; this is what I have, whenever I make the request it displays only one name: the last one.
request.get(`https://lan.api.pvp.net/championmastery/location/LA1/player/24244/topchampions?api_key=${API}`, (error, response, body) => {
let parsedInfo = JSON.parse(body)
var data = {
"id": [],
"points": []
}
for(x in parsedInfo) {
data.id.push(parsedInfo[x].championId)
data.points.push(parsedInfo[x].championPoints)
var checkChampId = parsedInfo[x].championId
}
request.get('http://ddragon.leagueoflegends.com/cdn/6.24.1/data/en_US/champion.json', (error, response, body) => {
let champParse = JSON.parse(body)
for(x in champParse.data) {
if(checkChampId == champParse.data[x].key) {
console.log(champParse.data[x].name)
}
}
})
Let me know if I need to explain my issue more in depth.
You are only saving the id of the last champ
var checkChampId = parsedInfo[x].championId
First you need to save all ids, you can create an array to store it
var champIds = [];
for(x in parsedInfo) {
data.id.push(parsedInfo[x].championId)
data.points.push(parsedInfo[x].championPoints)
// saves the id in the array
champIds.push(parsedInfo[x].championId);
}
Now with all ids you can check in the other loop if the key is present in the array:
for(x in champParse.data) {
// check if the key is in the array of ids you saved
if (champIds.indexOf(Number(champParse.data[x].key)) !== -1) {
console.log(champParse.data[x].name)
}
}
If the types are different you can search with another method
champIds.filter(function (id) { return id == champParse.data[x].key; }).length > 0
This is going to compare without considering the object type and if it finds anything that matches it will be true.
Your issue is that you are assigning the variable
var checkChampId = parsedInfo[x].championId inside of the encapsulated scope of the first for loop which causes it to be deleted after each cycle.
Define checkChampId globally and use it as an array of ids rather than a single value. or move your request code within the same scope as the definition of the checkChampId var
for (x in parsedInfo) {
data.id.push(parsedInfo[x].championId)
data.points.push(parsedInfo[x].championPoints)
var checkChampId = parsedInfo[x].championId
/* removed the } here */
request.get('http://ddragon.leagueoflegends.com/cdn/6.24.1/data/en_US/champion.json', (error, response, body) => {
let champParse = JSON.parse(body)
for (x in champParse.data) {
if (checkChampId == champParse.data[x].key) {
console.log(champParse.data[x].name)
}
}
} /* add the } here */
In the first for loop create an array and append your parsedInfo
for(var x = 0; x < in parsedInfo.length; x ++) {
data.id.push(parsedInfo[x].championId)
data.points.push(parsedInfo[x].championPoints)
var checkChampId = []
checkChampId.push(parsedInfo[x].championId)
also try this in second loop
for(var x = 0; x < champParse.data; x ++)
Related
I want to create a login by using js. For this, I want to use localStorage. It's easy to store just one email, since you can give it a key. But what if I want to create multiple entries for email? I've thought about using a variable (let's call it x) which is 0 when there is nothing in localStorage. It could be set to +1 any time a new Email is added. My idea would then be to write:
let x = 0;
function addMail{
usrInput = document.getElementById("userEmail").value;
x = x + 1;
localStorage.setItem("email" + x, usrInput);
}
That's the register part. But I'm lost when It comes to logging in. How can I check if that email the user types into the text-input (id = "usrEmail") is identical to any entry in localStorage?
Instead of storing email as the value in the local storage, you can store a whole array of emails by serializing it as JSON.
Push new email:
const emailsInStorage = JSON.parse(localStorage.get('emails') || '[]');
emailsInStorage.push('new#email.com');
localStorage.set('emails', JSON.stringify(emailsInStorage));
Check if email exists in the list:
const emailsInStorage = JSON.parse(localStorage.get('emails') || '[]');
const exists = emailsInStorage.includes('new#email.com');
Edit #1
Instead of constructing an array and serializing it as JSON, you can go ahead with your idea of storing different emails under different keys (email1, email2, etc.). Still, you'll have to store also the number of email keys you have already stored.
I attached an example you can play around with, but the JSON approach is better.
function getEmailsCount() {
return Number(localStorage.getItem('emails.count'));
}
function getEmailByIndex(index) {
return localStorage.getItem(`emails.${index}`);
}
function saveEmail(email) {
const nextIndex = getEmailsCount() + 1;
localStorage.setItem(`emails.${nextIndex}`, email);
localStorage.setItem('emails.count', nextIndex);
}
function isEmailExists(email) {
const emailsCount = getEmailsCount();
for (let i = 0; i <= emailsCount; i++) {
if (getEmailByIndex(i) === email) return true;
}
return false;
}
saveEmail('email1#gmail.com');
saveEmail('email2#gmail.com');
saveEmail('email4#gmail.com');
saveEmail('email5#gmail.com');
console.log(isEmailExists('email1#gmail.com')); // true
console.log(isEmailExists('email2#gmail.com')); // true
console.log(isEmailExists('email3#gmail.com')); // false
console.log(isEmailExists('email4#gmail.com')); // true
console.log(isEmailExists('email5#gmail.com')); // true
console.log(isEmailExists('email6#gmail.com')); // false
I've created a new project that should compare a name from Sheet1 with a list of names in Sheet2 and check if the name is already in that list. For that I chose a for-loop to get through the list in Sheet2 and compare every list entry with the name from Sheet1. Only if the name already exists in the list stuff should happen.
function myFunction() {
var tabSheet1 = 'Sheet1';
var tabSheet2 = 'Sheet2';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName(tabSheet1);
var sheet2 = ss.getSheetByName(tabSheet2);
var lastRow1 = sheet2.getLastRow() + 1;
var playerNameSheet1 = sheet1.getRange(1, 1).getValue();
for (var j = 1; j < lastRow1; j++) {
var playerNameSheet2 = sheet2.getRange(j, 1).getValue();
if (playerNameSheet2 == playerNameSheet1) {
...stuff...
}
}
}
Now my problem is that it seems like the script isn't able to identify that a name already exists in the list. Both values (playerNameSheet1 and playerNameSheet2) are completely identical (no space or other hidden obstacles), however the script would never continue with stuff in the if-statement. My example name to test my script was "Oliver Baumann".
I'm a bit confused about it - even more, because another comparison a bit later in the script code works just fine.
I've already tried to change the operator into === but that wouldn't work either.
if (playerNameSheet2 === playerNameSheet1) {
...stuff...
}
I've also observed that if I put a dot behind both variables I'm only able to choose further functions with playerNameSheet2, but not with playerNameSheet1. Maybe I did a typing error and am just too blind to see it? I don't know. Anyone an idea how to resolve the issue?
The complete project can be found here. However, a lot of stuff is in german and very rudimental. I just started it and haven't got time to clean it up. Just so you don't wonder.
You will likely benefit from a change to your inspection routine - currently what you have is not scalable due to the slow, repeated calls to the Spreadsheet Service. Use a batch method - getValues() - to return a Javascript Array that contains all the content you could want from your 'master list' of names:
// Create an N x 1 array of arrays, e.g. [ [r1c1], [r2c1], [r3c1], ... [rNc1] ],
// of data in column A in sheet2. There will be blanks at the end if other columns have more data.
var allNames = sheet2.getRange(1, 1, sheet2.getLastRow(), 1).getValues();
To check if the name from the first sheet is present, we can replace this code:
for (var j = 1; j < lastRow1; j++) {
var playerNameSheet2 = sheet2.getRange(j, 1).getValue();
if (playerNameSheet2 == playerNameSheet1) {
/* do stuff */
with this code (note j now starts at 0):
for (var j = 0; j < allNames.length; ++j) {
if (playerNameSheet1 === allNames[j][0]) {
/* do stuff */
If you only need to do stuff on a name once in the function call (e.g. you don't need to execute the loop body twenty times when the sheet 1 name is "Bob" and there are twenty instances of "Bob" on sheet 2), you can simplify checking allNames for a value with the Array#indexOf method. First, one must collapse the "2D" array of arrays of values into an array of values. We want to apply a function to every element of the outer array and construct an array of its outputs, so we choose to call Array#map on it:
var db = allNames.map(function (row) { return row[0]; });
The function we use simply returns the first element of the passed element - i.e. the value in the first column, resulting in an output like [ r1c1, r2c1, r3c1, ... rNc1 ].
The replacement code is then:
if (db.indexOf(playerNameSheet1) === -1) {
console.log({
message: "Did not find '" + playerNameSheet1 + "' in database.",
database: db, original: allNames, searched: playerNameSheet1
});
return;
}
/* do stuff */
Which says "if the name is not on sheet 2, log the failed lookup and then quit running the function." To promote actual logging, the log is sent to Stackdriver, which will keep it for much longer than the native Logger class would.
If your do stuff bits use the j index, you can still obtain that index and use the associated row in sheet 2:
var index = db.indexOf(playerNameSheet1);
if (index === -1) {
console.log({
message: "Did not find '" + playerNameSheet1 + "' in database.",
database: db, original: allNames, searched: playerNameSheet1
});
return;
}
/* do stuff with the user's existing row of data, e.g.
var userDataRow = sheet2.getRange(index + 1, 1, 1, sheet2.getLastColumn()).getValues();
var userData = userDataRow[0];
...
*/
A possible improvement to the indexOf modification, which I leave for you to investigate and/or implement, would be to use an Object to hold the names as "keys" (object properties) and the index of the associated sheet data (or even the data directly) as the associated value of the key-value pair.
you can try to convert data in array and compare in for-loop:
var dataRangeSpieler = sheetSpieler.getDataRange().getValues();
var dataRangeDBSpiele = sheetDBSpieler.getDataRange().getValues();
for (i in dataRangeSpieler ) {
for (j in dataRangeDBSpiele) {
if (dataRangeSpieler[i][1] == dataRangeDBSpiele[j][0]) {
Logger.log(dataRangeSpieler[i][1]); //Oliver Baumann
}
}
}
I'm trying to set objects into localStorage with a format similar to the following:
[{"1":{"property1":false,"property2":false}},{"2":{"property1":false,"property2":false}}]
Where I'd be able to set the 1 or 2 based on a dynamic value I'm getting from a REST call. What I have so far is:
// check if session exists and create if not
var StorageObject = JSON.parse(localStorage.getItem("session")) || [];
//see if the current id from the REST call is in storage and push with properties if not
if ( !StorageObject[thisItemsListID] ) {
var itemProperties = {};
itemProperties[thisItemsListID] = {};
itemProperties[thisItemsListID]["property1"] = false;
itemProperties[thisItemsListID]["property2"] = false;
StorageObject.push(itemProperties);
localStorage.setItem('session', JSON.stringify(StorageObject));
}
I can get the data into localStorage using this format but StorageObject[thisItemsListID] always gets into the if statement and generates a duplicate item in localStorage and I'm not sure how to access this with a variable. I'm trying to append the new ID if it doesn't exist so if {1:{} exists but current ID is 2 I need to push the new value.
I'm close here and maybe I need to reevaluate the format I'm storing the data string but I'm going in circles here and could use a point in the right direction.
Well, the duplicate item is happening in StorageObject.push(itemProperties).
Try this to update the object:
//StorageObject.push(itemProperties); <-- remove
StorageObject[thisItemsListID] = itemProperties;
[EDIT]
If you want to keep [{"1":{"property1":false,"property2":false}},{"2":{"property1":false,"property2":false}}]. To conditional would be a bit different.
var haveItem = StorageObject.filter(function(item){
return Objects.keys(item)[0] == thisItemsListID;
}).length > 0;
if ( !haveItem ) {
var itemProperties = {};
itemProperties[thisItemsListID] = {};
itemProperties[thisItemsListID]["property1"] = false;
itemProperties[thisItemsListID]["property2"] = false;
StorageObject.push(itemProperties);
localStorage.setItem('session', JSON.stringify(StorageObject));
}
Are you trying to update the object or just overwrite it? Filipes response illustrates how to update the entire storage object by just reassigning the object with the new value.
If you wanted to update just as section/ value of the object you could do so using a for loop. This would allow you to scan the array locate the one property and then remove it, updated it, overwrite it etc.
Here is an example of the loop. Bear in mind This is a snippet from a report library I was building. It uses angular $scope but it is a complex type doing a similar action to your update (here I am setting a label as a favorite/bookmark)
function OnFavoriteComplete(response) {
var id = response.config.data.reportId; //dynamic values set by client
var isFavorite = response.config.data.isFavorite;//dynamic values set by client
var arrayCount = $scope.reportList.length;
//loop my current collection and look for the property id of the label
//then check to see if true or false/this was a toggle enable disable
if (isFavorite) {
for (var i = 0, iLen = arrayCount; i < iLen; i++) {
if ($scope.reportList[i].reportId == id) {
$scope.reportList[i].isFavorite = false;
}
}
}
//if false update the property with the new value
else {
for (var i = 0, iLen = arrayCount; i < iLen; i++) {
if ($scope.reportList[i].reportId == id) {
$scope.reportList[i].isFavorite = true;
}
}
}
};
If you are using another framework like lowDash it has some really nice helper functions for updating and evaluating arrays.
I have a main object consisting of two main properties, data which contains messages and included which contains the senders of the messages. I want to create a new Array called messages which will contain all the values of both objects but in a way that every object inside this array will consist of the data values adding the correct sender as property to each of them.
I am able to separate the main object to two different ones, one containing the data and the other containing the senders.
if (jsonAPI.data) {
$.each(jsonAPI.data, function(index, value) {
dataObj[index] = value;
});
}
if (jsonAPI.included) {
$.each(jsonAPI.included, function(index, value) {
senders[value.id] = value;
});
}
I guess I have to make an iteration for every value of the dataObj and check if the relationships.sender.data.id is equal to senders.id then add the new property to dataObj, but I don't know how to write it.
What I say can be more clear in this fiddle https://jsfiddle.net/mosmic/f2dzduse/
Working jsfiddle: https://jsfiddle.net/f2dzduse/5/
var jsonAPI = {<snip>};
var dataObj = {};
if (jsonAPI.data) {
$.each(jsonAPI.data, function(index, value) {
dataObj[index] = value;
});
}
$.each(dataObj, function(index, value) {
//Prevent error if there is no sender data in included
if(jsonAPI.included.length - 1 >= index) {
//check if ids are equal
if(value.relationships.sender.data.id == jsonAPI.included[index].id) {
value.sender = jsonAPI.included[index];
}
}
});
console.log(dataObj);
This code assumes that jsonAPI.data.relationships.sender.data.id and jsonAPI.included.id are both in the same order!
If this is not always the case let me know and I'll rewrite the code to loop trough each jsonAPI.data and then loop trough jsonAPI.include to check for an equal id. This code will be slower since it will loop a total of jsonAPI.data.length X jsonAPI.include times.
Here's the updated code: https://jsfiddle.net/f2dzduse/6/
var jsonAPI = {<snip>};
var dataObj = [];
$.each(jsonAPI.data, function(x, data) {
dataObj[x] = data;
$.each(jsonAPI.included, function(y, included) {
if(data.relationships.sender.data.id == included.id) {
dataObj[x].sender = included;
}
});
});
console.log(dataObj);
In my Notes Database, I perform an audit when the document is saved. Pretty easy in LotusScript. I grab the original document (oDoc) from the server, then in the document I modified (mDoc), I do a Forall loop that gets the names of each item; forall item in mDoc.items. Grab the same item from oDoc, execute a function with the new item as an argument that will run down a case statement that will see if its a field we care about. if so, I update a set of list values in the document with "When", "Who", "What field", and the "New Value".
I'm doing this in a server side script. In trying this, I discovered a couple of interesting things;
currentDocument is the NotesXSPDocument that contains everything that was just changed.
currentDocument.getDocument() contains the pre-change values. It also returns a NotesDocument which has the "items" field that I can run through.
Thing is, I need something similar in the NotesXSPDocument. Is there a way in an iterative loop to grab the names and values of all items from there?
Here's the broken code. (Currently it's walking through the NotesDocument items, but those are the old values. I'd rather walk down the XSP document items)
function FInvoice_beginAudit() {
var original_doc:NotesDocument = currentDocument.getDocument();
var oItem:NotesItem;
var oItems:java.util.Vector = original_doc.getItems();
var iterator = oItems.iterator();
while (iterator.hasNext()) {
var oItem:NotesItem = iterator.next();
item = currentDocument.getItemValue(oItem.getName());
if (oItem == undefined) {
var MasterItem = ScreenAudit(doc,item,True)
if (MasterItem) { return true }
} else {
if (item.getValueString() != oItem.getValueString()) {
var MasterItem = ScreenAudit(doc,Item,True);
if (MasterItem) { return true }
}
}
}
}
You can get both versions of a document after submit - the original and the one with changed/new values:
original: var original_doc:NotesDocument = currentDocument.getDocument();
changed: var changed_doc:NotesDocument = currentDocument.getDocument(true);
This way you can compare the items for changes.
But, there is a pitfall: after assigning "changed_doc" to currentDocument.getDocument(true) the "original_doc" has the changed values too because both variables point to the same document. That's why we have to copy all items from currentDocument.getDocument() to a new temporary document first and only after get the changed values with currentDocument.getDocument(true). As an alternative you could read the original document from server like you do in LotusScript.
This is a code for detecting changed items as a starting point:
var original_doc:NotesDocument = database.createDocument();
currentDocument.getDocument().copyAllItems(original_doc, true);
var changed_doc:NotesDocument = currentDocument.getDocument(true);
var oItems:java.util.Vector = original_doc.getItems();
var iterator = oItems.iterator();
while (iterator.hasNext()) {
var oItem:NotesItem = iterator.next();
var itemName = oItem.getName();
var cItem:NotesItem = changed_doc.getFirstItem(itemName);
if (cItem.getText() !== oItem.getText()) {
print("changed: " + itemName);
}
oItem.recycle();
cItem.recycle();
}
original_doc.remove(true);
original_doc.recycle();