Create multiple localStorage entries automatically - javascript

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

Related

Compare user input with csv file, return second column value javascript

I came across the following topic, it just has 1 line instead of 2 columns.
How do I return the second value here (see topic below)
Compare my variable with a csv file and get the matching value in javascript
This is my CSV file values:
csv screenshot of columns
This is what I have currently
IT just checks the file for the serial number from the user and marks the div with text "Valid".
This Valid should have the second Columns value.
<script>
const checkm = document.getElementById('check');
checkm.addEventListener('click', serialChecker)
async function serialChecker(){
const url = 'http://localhost/validator/serials.csv';
const response = await fetch(url);
// wait for the request to be completed
const serialdata = await response.text();
console.log(serialdata);
const inputserialnumber = document.getElementById('serialnumber').value.toString();
console.log(inputserialnumber);
// serialdata.match(/inputserialnumber/)
// serialdata.includes(inputserialnumber)
if(serialdata.includes(inputserialnumber) == true && inputserialnumber.length == 7 ){
document.getElementById('validity').innerHTML = "Valid";
startConfetti(); // from confetti.js
}else {
document.getElementById('validity').innerHTML = "Invalid";
stopConfetti(); // from confetti.js
}
//document.getElementById('test').innerHTML = "Valid";
}
</script>
This is my console output
It shows the full csv(currently), & the users input
changed the csv data into to different arrays if that helps:
array
& Thanks all in advance for taking the time to reply to my silly question!
EXTRA Clarification:
What I'm trying to do is a validate website checker.
So the user inputs their serial through an simple input field. & I have the serials in a csv file with an extra column that has the name matching to the serial.
So if the user inputs 1234567 it is present in the CSV file, my current code returns value = true for that. as it is present in the CSV file.
But I want it to return the value next to 1234567 (so in the second Column) instead, in this case "test1". So I can use that value instead of just a standard "Valid" text to be pushed back onto the website.
You can match values of two arrays by their index. In your case, I think it's easiest to use Array.map() to return a transformed array based on the one you loop trough. So for example, if you have two arrays called namesArray and valuesArray, do the following:
const validationResults = valuesArray.map((value, index) => {
return {
valid: checkValidity(value), // or whatever your validation function is called
name: namesArray[index] // match the index of the namesArray with the index of this one (valuesArray)
};
// or `return namesArray[index] + ', valid: ' + checkValidity(value)`
});
This loops through the valuesArray, and validationResults will then be an array of what you return per each item in the map function above.
One important note is that this assumes the arrays are both in the same order . If you want to sort them, for instance, do this after this.
Looking up and registering the values in a Map seems like the best answer.
// ...
const serialdata = await response.text();
const seriallookup = new Map();
// Set all Serial values to Names
for (let s in serialdata.split("\n")) {
let data = s.split(',');
seriallookup.set(data[0], data[1]);
}
Using this, checking for a serial's existance could be done with .has()
if (inputserialnumber.length == 7 && seriallookup.has(inputserialnumber)) {
And set to the elements text using
document.getElementById('validity').innerHTML = serialdata.get(inputserialnumber);
If the .csv file most likely wouldn't change between multiple requests (or if you only send just one request), you should probably initialize and request the data outside of the function.
Thank you all for the feedback.
I have not been able to use your suggestions exactly as intended.
But I managed to combine the idea's and create a new piece that does the trick for me!
const checkm = document.getElementById('check');
checkm.addEventListener('click', serialChecker)
async function serialChecker(){
const url = 'http://localhost/validator2/naamloos.csv';
const response = await fetch(url);
// wait for the request to be completed
const serialdata = await response.text();
const table = serialdata.split('\r\n');
const serialsArray = [];
const nameArray = [];
table.forEach(row =>{
const column = row.split(',');
const sArray = column[0];
const nArray = column[1];
serialsArray.push(sArray);
nameArray.push(nArray);
})
var array1 = serialsArray,
array2 = nameArray,
result = [],
i, l = Math.min(array1.length, array2.length);
for (i = 0; i < l; i++) {
result.push(array1[i], array2[i]);
}
result.push(...array1.slice(l), ...array2.slice(l));
function testfunction(array, variable){
var varindex = array.indexOf(variable)
return array[varindex+1]
}
//calling the function + userinput for serial
const inputserialnumber = document.getElementById('serialnumber').value.toString();
console.log(testfunction(result, inputserialnumber))
if(serialsArray.includes(inputserialnumber) == true && inputserialnumber.length == 7 ){
document.getElementById('validity').innerHTML = "Valid " + testfunction(result, inputserialnumber);
startConfetti();
}else {
document.getElementById('validity').innerHTML = "Invalid";
stopConfetti();
}
}
Hope this can help someone out in having an input field on their website with a .csv file in the backend (possible to have multiple for the user to select with a dropdown box with the async function).
This will check the file & will return the value from the csv that matches the serial!(based on serial number & length of the serial number(7characters))

how to add an object to a list in localstorage

so basically i want to make a phone contacts app, and i try to save the saved contact to local storage
so this is the function when the save button clicked
saveContact(name, number){
//To check if the name input or phone input is not blank
if(nameInput.value == '' || phoneInput.value == ''){
info.style.display = 'block'
}
const firstLetter = name[0].toUpperCase()
const getContact = localStorage.getItem(firstLetter)
const storedObject = {
[name]:number
}
//If contact's first letter exists in localstorage
if (getContact){
const oldData = [JSON.parse(localStorage.getItem(firstLetter))]
oldData.push([storedObject])
const oldDataString = JSON.stringify(oldData)
localStorage.setItem(firstLetter, oldDataString)
const finalOldData = []
//i do a looping here to push each contact's object to a new array which is finalOldData
//but it doesn't work well. it doesn't actually add a new object to the array instead of replacing the old object with a new one
oldData.forEach(e => {
finalOldData.push(e[0])
})
const finalOldDataString = JSON.stringify(finalOldData)
localStorage.setItem(firstLetter, finalOldDataString)
}
//If contact's first letter doesn't exist in localstorage
else{
const storedObjectString = JSON.stringify([storedObject])
localStorage.setItem(firstLetter, storedObjectString)
this.clearSave()
}
}
so the issue is when i try to add a contact which its first letter exist in local storage and make it as a list
//and this is the result i want
Storage
​
A: "[{\"amber\":\"1242134\"},{\"annie\":\"123421\"}]"
​
length: 1
You can consider the code below, it is working as expected.
Changes
const oldData = [JSON.parse(localStorage.getItem(firstLetter))]
No need to put the result from JSON.parse into an array, it already is an array and also you can use the variable getContact instead of calling getItem again on localStorage.
oldData.push([storedObject])
No need to push an array into oldData, simply push storedObject.
I've removed the initial check for making testing easy, you can add it back.
function saveContact(name, number) {
if (!name || !number) {
return;
}
const firstLetter = name[0].toUpperCase();
const getContact = localStorage.getItem(firstLetter);
const storedObject = { [name]: number };
if (getContact) {
const oldData = JSON.parse(getContact);
oldData.push(storedObject);
const oldDataString = JSON.stringify(oldData);
localStorage.setItem(firstLetter, oldDataString);
} else {
const storedObjectString = JSON.stringify([storedObject]);
localStorage.setItem(firstLetter, storedObjectString);
}
}

How do I calculate the sum of numbers stored in LocalStorage?

I am new to JSON, so bear with me!
I am working on a website that stores values to LocalStorage via inputs. Each form input has the following function (only difference is formInput2, formInput3)
function formInput(e) {
// Save userInput from input
// Get form values
var input = document.querySelector('.input').value;
this.style.visibility = 'hidden';
smtBtn.style.display = 'inline-block'
var userInput = {
answer: input
}
// Test if bookmark is null
if (localStorage.getItem('bookmarks') === null) {
// Init Array
var bookmarks = [];
// Add to array
bookmarks.push(userInput);
// Set to LocalStorage
localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
} else {
// Get Bookmarks from LocalStorage
var bookmarks = JSON.parse(localStorage.getItem('bookmarks'));
// Add bookmark to array
bookmarks.push(userInput);
// Reset back to LocalStorage
localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
}
// Refetch bookmarks
fetchBookmarks();
// Prevent form from submitting
e.preventDefault();
}
I need to add the three numbers that are in local storage, and I am using this function:
function bookmarkMath() {
var bm1 = JSON.parse(localStorage.getItem('bookmarks')),
total = 0,
i;
for (i = 0; i < bm1.length; i++) {
total += bm1[i].answers;
}
console.log(total);
}
}
But alas, my output is NaN. :(
Any help would be very appreciated!!!!!!!
edit: In dev tools, this is what I get back with console.log(LocalStorage) - the numbers I have entered in the form on the site.
Storage {bookmarks: "[{"answer":"2"},{"answer":"4"},{"answer":"5"}]", length: 1}
bookmarks: "[{"answer":"2"},{"answer":"4"},{"answer":"5"}]"
length: 1
__proto__: Storage
Edit 2: I have updated the second ]function to include the JSON.parse. But now I am getting just the numbers 0245 as my result, NOT the sum of 0+2+4+5. Any help?? :p
You are on the right track by doing JSON.parse(). However, the value is in a string. You can see quote at the value it is mean will be threated as a string. You should convert it to number format like following:
total += parseInt(bm1[i].answers);
If you don't want to do parseInt() then your output should be :
{"answer": 2} //this one mean your value is Number
Instead:
{"answer":"2"} //this one mean your value is in String
I think I see it ... this statement looks "wrong, yet something that JavaScript would accept!"
var bm1 = JSON.parse(localStorage.getItem('bookmarks')),
total = 0,
i;
Notice the commas.
Instead, write this as three separate lines:
var var bm1 = JSON.parse(localStorage.getItem('bookmarks'));
var total = 0;
var i;
const bookmarks = JSON.parse(localStorage.getItem('bookmarks')) || []
const totalAnswers = bookmarks.map(o => +o.answer).reduce((a, b) => a + b)

Display another key's value if one value is the same

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 ++)

Get and set object values in localStorage array

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.

Categories