Incrementing key value when save data to local storage - javascript

I want to save different objects with different key to local storage every time my button clicked. But always key == 0 and records doesn't create, one record in local storage only update,I think this is because key is always same. How I can change this,to put different objects to local storage?
(function() {
window.onload = function() {
var key = 0;
var storage = new Storage();
document.getElementById('buttonCreate').onclick = function() {
var topicValue = document.getElementById("create-topic").value;
var statusValue = document.getElementById("create-status").value;
var descriptionValue = document.getElementById("create-description").value;
var ticket = {
topic: topicValue,
status: statusValue,
description: descriptionValue
};
storage.set(key, ticket);
key++;
}
}
})();
function Storage() {
this._ITEMS_DESCRIPTOR = 'items';
}
Storage.prototype.get = function() {
var fromStorage = localStorage.getItem(this._ITEMS_DESCRIPTOR);
return fromStorage ? JSON.parse(fromStorage) : [];
};
Storage.prototype.set = function(key, items) {
localStorage.setItem(key, JSON.stringify(items));
};

As localstorage API is implemented
You set an item for a keyName (1st argument):
localStorage.setItem(keyName, keyValue);
You get an item for a keyName:
var aValue = localStorage.getItem(keyName);
So in your case your Storage Object should be adapted since it seems like you need multiples keys but your get storage will only retrieve a fixed key='items'.
So, modify your Storage.get and pass a key when you call it:
function Storage() {
this._ITEMS_DESCRIPTOR = 'items'; // I guess a default key?
}
// let key be specified when method is called, or by default set it to the private property _ITEMS_DESCRIPTOR
Storage.prototype.get = function(key) {
var fromStorage = localStorage.getItem(key ? key : this._ITEMS_DESCRIPTOR);
return fromStorage ? JSON.parse(fromStorage) : [];
};
Storage.prototype.set = function(key, items) {
localStorage.setItem(key, JSON.stringify(items));
};

your key should be incrementing, but your storage.get is hard coded to a specific key so you'll never be able to retrieve them through its get method.
You should also verify that the method is being invoked
You could try a string vs a number as a key
storage.set("topic_" + key, ticket);
// alert("topic set for topic_" + key);
// retrieve and test data storage
// var data = localStorage.getItem("topic_" + key);
// alert("from storage:\n\n" + JSON.stringify(data));
key++;
Use F12 to review localStorage or simply test the data that is stored
function test(){
if (localStorage.length == 0)
alert("no items in localStorage");
for (var i = 0; i < localStorage.length; i++){
var key = localStorage.key(i);
var value = localStorage.getItem(key);
alert("storage [" + key + "] = " + value);
}
}

Related

Firebase .orderByChild().on runs more and more times every time it is called

I'm creating a guest list program that stores the guest list in Firebase RTDB and when I check people in and out my function runs several times more than it is supposed to. I've sent alerts to the console so I know how many times it has run. I have separate functions for both check in and check out operations so it may be that I am calling my db too many times?
//-------------------- Check In and Check In Helper Functions -------------------------
//Helper Function to Grab current List index
function printArray() {
var ref = database.ref('guestList')
ref.on('value', readData, errData);
}
function readData(data){
guestList=[];
var scores = data.val();
var keys = Object.keys(scores)
for (var i=0; i < keys.length; i++){
var k = keys[i]
var name = scores[k].name;
var inside = scores[k].Inside;
var timeIn = scores[k].TimeIn;
var timeOut = scores[k].TimeOut;
guestList[i] = {
name: name,
Inside: inside,
TimeIn: timeIn,
TimeOut: timeOut,
}
}
checkIn(guestList);
}
function errData(err){
console.log('Error!');
console.log(err);
}
//Helper Function to set text box to selected name
function checkInn(name){
console.log(name)
document.getElementById('checkIn').value = name;
}
//Check in
function checkIn(list) {
//Grabs current guest to be added or deleted from form text box
var name = document.getElementById('checkIn').value;
//Checks to see if user is in list of guests and isn't in the list of guest in the party
var guestsRef = firebase.database().ref("guestList/");
guestsRef.orderByChild("name").on("child_added", function(data) {
if (name == data.val().name) {
objIndex = list.findIndex((obj => obj.name == name));
guestsRef = firebase.database().ref("guestList/" + objIndex)
guestsRef.update({
Inside: "Yes",
TimeIn: getTime(),
})
guestsRef.off();
document.getElementById('checkIn').value = "";
alerts(name, true)
}
})
}
//------------------------- Check Out ------------------------------------------------------------
//Helper Function to Grab current List index
function printArrayy() {
var ref = database.ref('guestList')
ref.on('value', readOutData, errData);
}
function readOutData(data){
guestList=[];
var scores = data.val();
var keys = Object.keys(scores)
for (var i=0; i < keys.length; i++){
var k = keys[i]
var name = scores[k].name;
var inside = scores[k].Inside;
var timeIn = scores[k].TimeIn;
var timeOut = scores[k].TimeOut;
guestList[i] = {
name: name,
Inside: inside,
TimeIn: timeIn,
TimeOut: timeOut,
}
}
checkOut(guestList);
}
//Helper Function to set text box to selected name
function checkOutt(name){
console.log(name);
document.getElementById('checkOut').value = name;
}
//Check Out
function checkOut(list) {
//Grabs current guest to be added or deleted from form text box
var name = document.getElementById('checkOut').value;
//Checks to see if user is in list of guests and isn't in the list of guest in the party
var guestsRef = firebase.database().ref("guestList/");
guestsRef.orderByChild("name").on("child_added", function(data) {
if (name == data.val().name) {
objIndex = list.findIndex((obj => obj.name == name));
guestsRef = firebase.database().ref("guestList/" + objIndex)
guestsRef.update({
Inside: "No",
TimeOut: getTime(),
})
document.getElementById('checkOut').value = "";
guestsRef.off();
alerts(name, false)
}
})
}
//Placeholder to alert user when a succesful check in or check out function runs
function alerts(name, Boolean){
if(Boolean){
console.log(name + " has been checked in!")
}
else{
console.log(name + " has been checked out!")
}
}
Here is the screenshot of my output. Thanks in advance!
Edit: Forgot to mention and apologize for my excessive use of helper functions! My HTML form calls printArrayy() and printArray first for each function!
have you tried once instep on, i mean:
ref.once('value', readOutData, errData); }

How I can get object from another function

I'm trying to do a Shopping cart with HTML and JS. So I'm using (https://www.smashingmagazine.com/2019/08/shopping-cart-html5-web-storage/).
In my function save(), I have,
`function save(id, title, price) {
// var button = document.getElementById('button');
// button.onclick=function(){
// var test = localStorage.setItem('test', id);
window.location.href='/panier'
var obj = {
title: title,
price: price
};
localStorage.setItem(id, JSON.stringify(obj));
var test = localStorage.getItem(id);
var getObject = JSON.parse(test);
console.log(getObject.title);
console.log(getObject.price);
}`
so to get "title for example I don't have problem in my function save(), but in my function doShowAll(),
function CheckBrowser() {
if ('localStorage' in window && window['localStorage'] !== null) {
// We can use localStorage object to store data.
return true;
} else {
return false;
}
}
function doShowAll() {
if (CheckBrowser()) {
var key = "";
var id = localStorage.getItem(id);
var list = "<tr><th>Item</th><th>Value</th></tr>\n";
var i = 0;
//For a more advanced feature, you can set a cap on max items in the cart.
for (i = 0; i <= localStorage.length-1; i++) {
key = localStorage.key(i);
list += "<tr><td>" + key + "</td>\n<td>"
+ localStorage.getItem(key) + "</td></tr>\n";
}
//If no item exists in the cart.
if (list == "<tr><th>Item</th><th>Value</th></tr>\n") {
list += "<tr><td><i>empty</i></td>\n<td><i>empty</i></td></tr>\n";
}
//Bind the data to HTML table.
//You can use jQuery, too.
document.getElementById('list').innerHTML = list;
} else {
alert('Cannot save shopping list as your browser does not support HTML 5');
}
}
I can't to get my object.
I have tried:
if (CheckBrowser()) {
var key = "";
var id = localStorage.getItem(id);
var getObject = JSON.parse(test);
}
var list = "<tr><th>Item</th><th>Value</th></tr>\n";
var i = 0;
//For a more advanced feature, you can set a cap on max items in the cart.
for (i = 0; i <= localStorage.length-1; i++) {
key = localStorage.key(i);
list += "<tr><td>" + key + "</td>\n<td>" + getObject.title
+ localStorage.getItem(key) + "</td></tr>\n";
}
but when I add something else than key or localStorage.getItem(key) in "list +=" nothing is displayed in my html view.
So I just Want to display data from my object in the PHP array in doShowAll() function.
Hoping to have clear and wainting a reply. Thank you

Get multiple values with local storage

I'd like to retrieve the name and the date of created tasks. I managed to put the value taskMessage in local storage, but I don't know how to add taskName as well. This is the code I currently have :
$(document).ready(function () {
var i = 0;
for (i = 0; i < localStorage.length; i++) {
var taskID = "task-" + i;
$('.task-container').append("<li class='item-content' id='" + taskID + "'>" + localStorage.getItem(taskID) + "</li>");
}
$('.floating-button').on('click', function () {
myApp.prompt('', 'Add Task', function (task) {
if (task !== "") {
myApp.prompt('', 'Choose time', function (time) {
var d1 = new Date();
d1.setHours(time, 0, 0, 0);
var hour = d1.getHours();
if (time > 0 && time < 25) {
var d2 = new Date();
var currenttime = d2.getHours();
if (time > currenttime) {
var taskID = "task-" + i;
var taskMessage = hour;
var taskName = task;
localStorage.setItem(taskID, taskMessage);
var newtask = '<li class="item-content ' + taskID + '"><div class="item-inner"><div class="item-title" >' + taskName + '</div><div class="item-after"> ' + taskMessage + ':00</div> </div></li>';
var taskitem = $('#' + taskID);
$('.task-container').append(newtask);
}
else {
myApp.addNotification({
message: 'Please choose a valide time period'
});
}
}
else {
myApp.addNotification({
message: 'Please choose a value between 1 and 24'
});
}
});
}
else {
myApp.addNotification({
message: 'Please enter a valid name'
});
}
});
});
});
First you should get the data into a variable
var getData =
{
"firstData":"data1",
"secondData":"data2",
"thirdData": "data3"
}
Then you can set the above data's in localStorage...
localStorage.setItem('dataKey', JSON.stringify(getData ));
Then get....
var val = localStorage.getItem('dataKey');
Enjoy!!!
If you want to store two different values in localStorage then you can do somrthing like this :
setItem in localStorage two times with different keys.
localStorage.setItem("message", taskMessage);
localStorage.setItem("name", taskName);
Store both the values in an object.
var obj = {
"message": taskMessage,
"name": taskName
}
var val = localStorage.setItem("task", obj);
typeof val: string
Value of val: [object Object]
setItem method convert the input to a string before storing it.
Try this :
// Put the object into storage
localStorage.setItem('task', JSON.stringify(obj));
// Retrieve the object from storage
var val = localStorage.getItem('obj');
console.log('retrievedValue: ', JSON.parse(val));
You can easily store values in localstorage using following example.
//Save the values to Localstorage
localStorage.setItem('first','firstvalue');
localStorage.setItem('second','secondvalue');
//Retrieve the values from localstorage
localStorage.getItem('first')
//"firstvalue"
localStorage.getItem('second')
//"secondvalue"
localStorage saves item key&value as string,so you call setItem with an object/json object,you must serialize json to string by JSON.stringify() method.when you get value you need parse string as json object using JSON.parse() method.
Test
test(`can't retrieve json from localStorage if raw json data saved`, () => {
localStorage.setItem('foo', {foo: 'bar'});
expect(localStorage.getItem('foo')).toEqual('[object Object]');
});
test(`retrieve json value as string from localStorage`, () => {
localStorage.setItem('foo', JSON.stringify({foo: 'bar'}));
let json = JSON.parse(localStorage.getItem('foo'));
expect(json.foo).toEqual('bar');
});
test(`key also be serialized`, () => {
localStorage.setItem({foo: 'bar'}, 'value');
expect(localStorage.getItem('[object Object]')).toEqual('value');
});
test('supports bracket access notation `[]`', () => {
localStorage.setItem('foo', 'bar');
expect(localStorage['foo']).toEqual('bar');
});
test('supports dot accessor notation `.`', () => {
localStorage.setItem('foo', 'bar');
expect(localStorage.foo).toEqual('bar');
});

Javascript check if url param exists

I'm running an A/B test to see if showing more items is better for conversion. But it seems that the code sometimes causes errors.. But I can't find any errors and don't know when they occur.
In my test I check whether the url param IC exists and if it doesn't exists I will add this.
This is my code:
function checkIfAlreadyPaginated()
{
var field = 'IC';
var url = window.location.href;
if(url.indexOf('?' + field + '=') != -1)
return true;
else if(url.indexOf('&' + field + '=') != -1)
return true;
return false;
}
function insertParam(key, value) {
key = encodeURIComponent (key); value = encodeURIComponent (value);
var kvp = document.location.search.substr(1).split('&');
if (kvp == '') {
return '?' + key + '=' + value;
}
else {
var i = kvp.length; var x; while (i--) {
x = kvp[i].split('=');
if (x[0] == key) {
x[1] = value;
kvp[i] = x.join('=');
break;
}
}
if (i < 0) { kvp[kvp.length] = [key, value].join('='); }
return '?'+kvp.join('&');
}
}
var itemsPerPage = 48;
if(!checkIfAlreadyPaginated())
{
document.location.search = insertParam('IC', itemsPerPage);
}
Does someone spot possible issues? I'm running the test via VWO.com.
If there is a Javascript error you should see it in the browser console and share it with us.
In any case, I would do it by creating a JS Object first. I find it easier to work with.
In the following code I added the option to do the checking for multiple params of the querystring. If you only need to check the IC you can simplify it a bit. I tested it on a blank test.html.
<script type="text/javascript">
// get the current params of the querystring
var querystringItems = document.location.search.substr(1).split('&');
// create an object
var querystringObject = {};
for(i=0;i<querystringItems.length;++i) {
param = querystringItems[i].split('=');
querystringObject[param[0]] = param[1];
}
// Define the keys to be searched for and their default value when they are not present
var requiredKeys = {"IC":48, "test": "me"};
// Do the checking on the querystringObject for each requiredKeys
var doreload = false;
for (var key in requiredKeys) {
if (typeof querystringObject[key] == 'undefined') {
doreload = true;
// Create the missing parameter and assign the default value
querystringObject[key] = requiredKeys[key];
}
}
// If any of the requiredKeys was missing ...
if (doreload) {
// rebuild the querystring
var querystring = '?';
for (var key in querystringObject) {
querystring+=key+'='+querystringObject[key]+'&';
}
querystring=querystring.substr(0,querystring.length-1);
// reload page
document.location.search = querystring;
}
// assign the values to javascript variables (assuming you had it like this because you needed it)
var itemsPerPage = querystringObject.IC;
</script>
Here is an example to check this:
//get URL params into string:
paramStr = window.location.substring(window.location.indexOf('?'), window.location.length;
//turn string into array
paramArray = paramStr.split('&');
//prepare final array of params
params = {};
//prepare the index of IC parameter
icLoc = -1; //this is negative 1 so that you know if it was found or not
//for each item in array
for(var i in paramArray){
//push its name and value to the final array
params.push(paramArray[i].split('='));
//if the parameter name is IC, output its location in array
if(params[i][0] === 'IC'){
icLoc = i;
}
}
If IC is not found, icLoc will be -1.
If it is found, the value of IC in the URL parameters is params[icLoc][1]
Example result for query string ?foo=bar&code=cool&IC=HelloWorld:
params = {'foo': 'bar', 'code': 'cool', 'IC': 'HelloWorld'}
icLoc = 2
Example for query string ?foo=bar&code=cool:
params = {'foo': 'bar', 'code': 'cool'}
icLoc = -1
Here id is the param I'm using for a test. Pass the argument which you want to check whether it exists or not.
function queryParamExistUrl(param = '') {
if (new URLSearchParams(window.location.search).get(param) != null)
return true
return false
}
console.log(queryParamExistUrl('id'))

Cannot read 'xyxyx' property of undefined even if element exist

I have two HTML inputs (type="email", type="number") and my Angular app watches them using $formatters and $parsers. The errors are stored in an array and when user insert an email which contains "#gmail" the error is removed from the array.
app.controller('form1Controller', function($scope, UserService) {
$scope.formCompleted = false;
$scope.errors = UserService.errors;
//handle the user email input.
$scope.storeEmailErr = function(data) {
var correctKey = "#gmail";
var key = "#userEmail";
var res = {};
if (data != null) {
res = $scope.handleError(data, emailIn, correctKey, key, $scope.errors);
$scope.errors = res[0];
UserService.errors = res[0];
emailIn = res[1];
}
};
//handle the user email input.
$scope.storeIdErr = function(data) {
var correctKey = "0000";
var key = "#userId";
var res = {};
if (data != null) {
res = $scope.handleError(data, idIn, correctKey, key, $scope.errors);
$scope.errors = res[0];
idIn = res[1];
}
};
}
This is the code that adds and removes errors from array. And here i suppose is the problem
function theIndexOf(val) {
console.log("find index in array of length: " + errorsDescription.length)
for (var i = 0; i < errorsDescription.length; i++) {
if (errorsDescription[i].selector === val) {
return i;
}
}
}
app.run(function($rootScope){
$rootScope.handleError = function(data, elemIn, correctKey, key, errorArray){
var idx = theIndexOf(key);
console.log("get index >>>>> " + idx);
var obj = errorsDescription[idx];
//if user didn't put correct word i.e. #gmail or 0000
if (data.indexOf(correctKey) < 0) {
if (!elemIn) {
errorArray.push(obj);
elemIn = true;
}
} else {
if (elemIn) {
$.each(errorArray, function(i){
if(errorArray[i].selector === key) {
errorArray.splice(i, 1);
elemIn = false;
}
});
}
}
return [errorArray, elemIn];
}
});
The problem is that when I insert i.e. "test#gmail.com", the error is deleted from the array and when I insert correct data again it tells me that cannot read 'yyy' property of undefined.
Here is my plunker.
https://plnkr.co/edit/l0ct4gAh6v10i47XxcmT?p=preview
In the plunker, type in the fields 'test#gmail' and test0000 for the Number, then remove data then insert again the same data to see the problem
Any help would be much appreciated!
EDIT: Working plunkr here: https://plnkr.co/edit/8DY0Cd5Pvt6TPVYHbFA4
The issue is here:
var obj = errorsDescription[idx];
//if user didn't put correct word i.e. #gmail or 0000
if(data.indexOf(correctKey) < 0){
// console.log("You must put correct word");
if(!elemIn){
errorArray.push(obj);
elemIn = true;
}
}
When your Personal Number error is removed, the logic above pushes undefined to your errorArray (because elemIn is false). Your storeIdErr methond:
$scope.storeIdErr = function(data){
var correctKey = "0000";
var key = "#userId";
var res = {};
if(data != null){
res = $scope.handleError(data, idIn, correctKey, key, $scope.errors);
$scope.errors = res[0];
idIn = res[1];
}
};
reads this value (res[0]) and stores it in $scope.errors which ultimately is iterated over on the next input event by:
function theIndexOf(val){
console.log("find index in array of length: " + errorsDescription.length)
for(var i = 0; i < errorsDescription.length; i++){
if(errorsDescription[i].selector === val){
return i;
}
}
}
due to your factory returning that object when asked for errors. To fix this, you should keep a static list that you never remove from which provides the error definitions. This is what you should refer to when you push to errorArray in your first code block.
The issue you are having is with this block of code here:
$.each(errorArray, function(i){
if(errorArray[i].selector === key) {
errorArray.splice(i, 1);
elemIn = false;
}
});
When you call splice, you are modifying the length of the array. $.each is looping over the length of the array, and is not aware of the length change. (I don't know the internal workings of $.each, but I'm guessing it caches the length of the array before starting, for performance reasons.) So, after you splice out the first error, the loop is still running a second time. At this point, errorArray[1] no longer exists, which is causing your undefined error.
See this question for reference: Remove items from array with splice in for loop

Categories