Update JSON values with associated key - javascript

I am trying to collect the unique json data, I mean if the key exists the update its value. But not succeed to update the value of existing key.
var fpr_data = [{"rfr_id":"7","user_id":"5","fp_id":"10","raw_id":"3","raw_qty":"20.00","raw_wastage":"2","raw_name":"Buttons"},
{"rfr_id":"9","user_id":"5","fp_id":"10","raw_id":"4","raw_qty":"500.00","raw_wastage":"0","raw_name":"Yarn"},
{"rfr_id":"8","user_id":"5","fp_id":"10","raw_id":"5","raw_qty":"2.00","raw_wastage":"1","raw_name":"Needle"},
{"rfr_id":"7","user_id":"5","fp_id":"10","raw_id":"3","raw_qty":"20.00","raw_wastage":"2","raw_name":"Buttons"}];
var qty = 2, coll={}, _qty=0.00,_wastage=0.00;
// Filter and modify JSON data
$.each(fpr_data, function(i, data) {
_qty = data.raw_qty * qty;
_wastage = data.raw_wastage * qty;
// Next time add on existing keys
if( coll[data.raw_id] == data.raw_id ) {
var q = coll[data.raw_id].qty + _qty;
var w = coll[data.raw_id].wastage + _wastage;
coll[data.raw_id] = {"qty":q, "wastage":w};
}
else {
coll[data.raw_id] = {"qty":_qty, "wastage":_wastage};
}
});
console.log(coll);
In fpr_data there is raw_id that i want to collect unique ids and if the raw_id found in object then update its qty and wastage with raw_qty and raw_wastage. I got Unique JSON data but quantity and wastage are not getting update. What wrong i have done? You can find the same codes in fiddle and check the result in console.
Expected: The value of qty in 3 should be 80
JSFIDDLE

Below condition will not give you correct comparison, when object already exists in array.
if( coll[data.raw_id] == data.raw_id ) {
I think you should just do:
if(coll[data.raw_id]) {
If I understand you correctly try this example
if(coll[data.raw_id]) {
var q = coll[data.raw_id].qty + _qty;
var w = coll[data.raw_id].wastage + _wastage;
coll[data.raw_id] = {"qty":q, "wastage":w};
}
else {
coll[data.raw_id] = {"qty":_qty, "wastage":_wastage};
}

You use jQuery, so enjoy the jQuery.extend() function :
var fpr_data = [{"rfr_id":"7","user_id":"5","fp_id":"10","raw_id":"3","raw_qty":"20.00","raw_wastage":"2","raw_name":"Buttons"},{"rfr_id":"9","user_id":"5","fp_id":"10","raw_id":"4","raw_qty":"500.00","raw_wastage":"0","raw_name":"Yarn"},{"rfr_id":"8","user_id":"5","fp_id":"10","raw_id":"5","raw_qty":"2.00","raw_wastage":"1","raw_name":"Needle"}, {"rfr_id":"7","user_id":"5","fp_id":"10","raw_id":"3","raw_qty":"20.00","raw_wastage":"2","raw_name":"Buttons"}];
console.log(fpr_data);
var qty = 2, coll={}, _qty=0.00,_wastage=0.00;
// Filter and modify JSON data
$.each(fpr_data, function(i, data) {
_qty = data.raw_qty * qty;
_wastage = data.raw_wastage * qty;
// Next time add on existing keys
var currentObj = coll[data.raw_id]; // Try not to repeat yourself ;-)
if( currentObj == data.raw_id ) {
var q = currentObj.qty + _qty;
var w = currentObj.wastage + _wastage;
console.log(data);
coll[data.raw_id] = $.extend(data, {"qty":q, "wastage":w});
}
else {
coll[data.raw_id] = $.extend(data, {"qty":_qty, "wastage":_wastage});
}
});
console.log(coll);
I hope this is what you were looking for.

Related

Delete element from array when deleting record from localStorage

I have a localStorage object like this:
Key: jpxun
Value: [{"id":"0","name":"royal"},{"id":"1","name":"tippins"},{"id":"4","name":"leviosa"},{"id":"5","name":"vicious"}]
I have this JS to display output the localStorage:
var jpxun = JSON.parse(localStorage.getItem('jpxun')) || [];
if (jpxun) {
var jpxun_length = jpxun.length;
} else {
var jpxun_length = 0;
}
var hst = document.getElementById("usernames");
var MyUsernames = JSON.parse(localStorage.getItem("jpxun"));
if (jpxun_length > 0) {
// declare array to hold items for outputting later in plain text format
var plain_text_array = [];
for (var i = 0; i < MyUsernames.length; i++) {
var un1 = MyUsernames[i].name;
hst.innerHTML += "<li>" +"<a id="+MyUsernames[i].id + " href='#content' onclick='deleteById(this)'>x </a>" + un1 + "</li>";
// add word to plain text array
plain_text_array.push(un1);
}
}
Each element is outputted in a list item with an 'x' as a hyperlink so that it can be clicked and that element is deleted from localStorage.
This is the code to delete the item from localStorage:
var deleteById = function ( self ){
MyUsernames = MyUsernames.filter(function(elem) {
return elem.id !== self.id;
});
localStorage.setItem("jpxun",JSON.stringify(MyUsernames));
self.parentNode.parentNode.removeChild(self.parentNode);
}
That works fine.
Unfortunately I don't really understand how the code works in deleteById.
As that is the case, I am stuck on working out how to delete the corresponding record from plain_text_array when its value is deleted from localStorage.
I would try to find the text in the array thats includes that string 'id="item_id"':
plain_text_array = plain_text_array.filter(item => !item.includes(`id="${self.id}"`));
Just add it in the end of deleteById function.

Parsing data from api in javascript

I am trying to parse data from a wordpress json api to my ionic app, Data from api is coming as:
{
"event_0_date_from":["20191015"],
"event_0_date_to":["20190926"],
"event_0_event":["Winter Vacation"],
"event_0_description":["Winter vacation"],
"event_1_date_from":["20190917"],
"event_1_date_to":["20190930"],
"event_1_event":["Dashain Vacation"],
"event_1_description":["--some-data--"],
"event_2_date_from":["--some-data--"],
"event_2_date_to":["--some-data--"],
"event_2_event":["--some-data--"],
"event_2_description":["--some-data--"],
---------------
-------------
--------------
-------------
"event":["3"] this shows total number of events
}
Using javascript, how would I format the above data and save it to some variable so that I can render it easily?
events:[
{
"date_from":"20191015",
"date_to":"20190926",
"event":"Winter Vacation",
"description":"Winter vacation"
},
{
"date_from":"20191015",
"date_to":"20190926",
"event":"Winter Vacation",
"description":"Winter vacation"
},
{
"date_from":"--some-data--",
"date_to":"--some-data--",
"event":"--some-data--",
"description":"--some-data--"
},
---------------
-------------
--------------
-------------
]
I tried so many methods but none are working.
I think your just should take "yourObjekt.event[0]" for a counter like:
var newObjekt = [];
for (var i=0; i<yourObjekt.event[0]; i++) {
newObjekt[i] = {
date_from: yourObjekt["event_"+i+"_date_from"][0],
date_to: yourObjekt["event_"+i+"_date_to"][0],
event: yourObjekt["event_"+i+"_event"][0],
description: yourObjekt["event_"+i+"_description"][0]
}
}
You just need to iterate over your json object. Within each iteration create a new map and push this newly created map into an array. Following is working snippet.
let data = {
"event_0_date_from":["20191015"],
"event_0_date_to":["20190926"],
"event_0_event":["Winter Vacation"],
"event_0_description":["Winter vacation"],
"event_1_date_from":["20190917"],
"event_1_date_to":["20190930"],
"event_1_event":["Dashain Vacation"],
"event_1_description":["--some-data--"],
"event_2_date_from":["--some-data--"],
"event_2_date_to":["--some-data--"],
"event_2_event":["--some-data--"],
"event_2_description":["--some-data--"],
"event":["3"]
}
let array = [];// Initialize an array
let index = data.event[0];// Number of events
for(let i=0;i<index;i++){
let map = {};//Initialize a new map in each iteration.
map.date_from = data["event_"+i+"_date_from"][0];
map.date_to = data["event_"+i+"_date_to"][0];
map.event = data["event_"+i+"_event"][0];
map.description = data["event_"+i+"_description"][0]
array.push(map);// finally push map into array
}
console.log(array);
Try this code, it will include all event attributes in a dynamic way
var output = [];
for(var key in datas){
// parse key
var keyParts = key.split('_');
var value = datas[key];
// ignore "event" total
if(keyParts.length > 1){
var key = keyParts.slice(2).join('_'); // generate correct key from parts
var index = keyParts[1]; // indexes : 0, 1, 2, etc.
// initialize in first call
if(output.hasOwnProperty(index) === false){
output[index] = {}
}
// append to output
output[index][key] = value
}
}
Withing 20 minutes with Googling (+ few minutes for proper adjustment of counters) ... (wrote JS few times in whole life)
I was not sure how to load it into String and did not wanted to escape whole string, so I am loading it from a text file
Input data:
{
"event_0_date_from":["20191015"],
"event_0_date_to":["20190926"],
"event_0_event":["Winter Vacation"],
"event_0_description":["Winter vacation"],
"event_1_date_from":["20190917"],
"event_1_date_to":["20190930"],
"event_1_event":["Dashain Vacation"],
"event_1_description":["--some-data--"],
"event_2_date_from":["--some-data--"],
"event_2_date_to":["--some-data--"],
"event_2_event":["--some-data--"],
"event_2_description":["--some-data--"]
}
Page and script:
<!DOCTYPE HTML>
<html>
<body>
<input type="file" id="upload">
<script>
document.getElementById('upload').addEventListener('change', readFileAsString)
function readFileAsString() {
var files = this.files;
if (files.length === 0) {
console.log('No file is selected');
return;
}
var reader = new FileReader();
reader.onload = function(event) {
//console.log('File content:', event.target.result);
var inputStr = event.target.result;
//console.log(inputStr);
var obj = JSON.parse(inputStr);
//console.log(obj);
var hasNext=true;
var counter = 0;
while(hasNext){
var properties =["date_from","date_to","event","description"];
var propertyPrefix = "event_"
var prop = propertyPrefix + counter + "_" + properties[0];
if(obj.hasOwnProperty(prop)){
console.log("element #" + counter + ": ")
for(var i = 0; i< properties.length;i++){
var propToPrint = propertyPrefix + counter + "_" + properties[i];
//console.log("loading: " + propToPrint)
console.log(" " + obj[propToPrint]);
}
counter++;
}else{
hasNext = false;
}
}
};
reader.readAsText(files[0]);
}
</script>
</body>
</html>
Result:
element #0:
20191015
20190926
Winter Vacation
Winter vacation
element #1:
20190917
20190930
Dashain Vacation
--some-data--
element #2:
--some-data--
--some-data--
--some-data--
--some-data--
So, eg. this way its possible :)

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

Javascript | Objects, Arrays and functions

may be you can help me. How can I create global object and function that return object values by id?
Example:
var chat = {
data : {
friends: {}
}
}
....
/*
JSON DATA RETURNED:
{"users": [{"friend_id":"62","name":"name","username":"admin","thumb":"images/avatar/thumb_7d41870512afee28d91.jpg","status":"HI4","isonline":""},{"friend_id":"66","name":"Another name","username":"regi","thumb":"images/avatar/thumb_d3fcc14e41c3a77aa712ae54.jpg","status":"Всем привет!","isonline":"avtbsl0a6dcelkq2bd578u1qt6"},{"friend_id":"2679","name":"My name","username":"Another","thumb":"images/avatar/thumb_41effb41eb1f969230.jpg","status":"","isonline":""}]}
*/
onSuccess: function(f){
chat.data.friends = {};
for(var i=0; i< f.users.length;i++){
chat.data.friends.push(f.users[i])
}
}
How can I create a new function (It will return values by friend_id)?
get_data_by_id: function (what, friend_id) {
/*obj.what = getfrom_globalobject(chat.data.friends???)*/
}
Example of use:
var friend_name = get_data_by_id(name, 62);
var friend_username = get_data_by_id(username, 62);
var friend_avatar = get_data_by_id(thumb, 62);
Try:
get_data_by_id: function (what, friend_id) {
return chat.data.friends[friend_id][what];
}
... but use it like:
var friend_name = get_data_by_id('name', 62);
...and set up the mapping with:
for(var i=0; i< f.users.length;i++){
chat.data.friends[f.users[i].friend_id] = f.users[i];
}
You cannot .push() to an object. Objects are key => value mappings, so you need to use char.data.friends[somekey] = f.users[i];
If you really just want a list with numeric keys, make x5fastchat.data.friends an array: x5fastchat.data.friends = [];
However, since you want to be able to access the elements by friend_id, do the following:
onSuccess: function(f){
x5fastchat.data.friends = {};
for(var i=0; i< f.users.length;i++){
chat.data.friends[f.users[i].friend_id] = f.users[i]
}
}
get_data_by_id: function (what, friend_id) {
obj[what] = chat.data.friends[friend_id][what];
}
Note the obj[what] instead of your original obj.what: When writing obj.what, what is handled like a string, so it's equal to obj['what'] - but since it's a function argument you want obj[what].
Take a look at the following code. You can simply copy paste it into an HTML file and open it. click "go" and you should see the result. let me know if I did not understand you correctly. :
<script>
myObj = { "field1" : { "key1a" : "value1a" }, "field2" : "value2" }
function go()
{
findField(myObj, ["field2"])
findField(myObj, ["field1","key1a"])
}
function findField( obj, fields)
{
var myVal = obj;
for ( var i in fields )
{
myVal = myVal[fields[i]]
}
alert("your value is [" + myVal + "]");
}
</script>
<button onclick="go()">Go</button>
I would recommend using the friend objects rather than getting them by id and name.
DATA = {"users": [{"friend_id":"62","name":"name","username":"admin","thumb":"images/avatar/thumb_7d41870512afee28d91.jpg","status":"HI4","isonline":""},{"friend_id":"66","name":"Another name","username":"regi","thumb":"images/avatar/thumb_d3fcc14e41c3a77aa712ae54.jpg","status":"Всем привет!","isonline":"avtbsl0a6dcelkq2bd578u1qt6"},{"friend_id":"2679","name":"My name","username":"Another","thumb":"images/avatar/thumb_41effb41eb1f969230.jpg","status":"","isonline":""}]}
// simple data store definition
Store = {items:{}};
NewStore = function(items){
var store = Object.create(Store);
store.items = items || {};
return store
};
Store.put = function(id, item){this.items[id] = item;};
Store.get = function(id){ return this.items[id]; };
Store.remove = function(id){ delete this.items[id]; };
Store.clear = function(){ this.items = {}; };
// example
var chat = {
data : {
friends : NewStore()
}
}
// after data loaded
chat.data.friends.clear();
for( var i = 0; i < DATA.users.length; i += 1 ){
var user = DATA.users[i];
chat.data.friends.put( user.friend_id, user );
}
getFriend = function(id){ return chat.data.friends.get( id ); }
var friend = getFriend(66);
console.log(friend.name);
console.log(friend.username);
console.log(friend.thumb);

Categories