Not able to find inside the json object - javascript

I have one code to iterate the code and want the item of product by compare the category for example :
if category is "car" then product inside that array should be iterate with index not by name
html
<ul class="menulist"></ul>
<div class="content"></div>
js
var jsonData;
$(document).ready(function () {
$.ajax({
url: "product.json",
dataType: "json",
error: function () {
},
success: getData
});
function getData(data) {
alert(data)
for (i = 0; i < data.length; i++) {
var menulistdata = data[i].category,
menulist = '<li class="" data-att="' + menulistdata + '">' + menulistdata + '</li>'
$(".menulist").append(menulist);
}
$('.menulist li').on('click', function () {
var list = $(this).text();
for (i = 0; i < data.length; i++) {
alert(i)
var productData = data[i].products;
if (data[i].category == list) {
$(".content").append(productData.BMG[i].image + productData.BMG[i].date + productData.BMG[i].size);
}
}
})
}
});
json
[
{
"category":"car",
"products": {
"BMG" : [{
"image" : "images/cars/BMW.jpg",
"date": "5-May-2015",
"type": "JPGE image",
"size": "1132 KB"
}],
"verna":[{
"image" : "images/cars/Verna.jpg",
"date": "5-May-2015",
"type": "JPGE image",
"size": "1132 KB"
}]
}
},
{
"category":"Nature",
"products": {
"Nature Mood At Night" : [{
"image" : "images/nature/Night.jpg",
"date": "5-May-2015",
"type": "JPGE image",
"size": "1132 KB"
}],
"Snowfall on Hut":[{
"image" : "images/nature/Hut.jpg",
"date": "5-May-2015",
"type": "JPGE image",
"size": "1132 KB"
}]
}
}
]
Working Fiddle

data[0].products is of type object – you cannot iterate over an object by indices, only by named keys. Use the for..in statement to iterate over an object.
for( var key in data[0].products ) {
console.log( data[0].products[key] );
}
See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

What I understand is you want to append all your car properties. So here is code fiddle
$('.menulist li').on('click', function () {
var list = $(this).text();
for (i = 0; i < data.length; i++) {
var productData = data[i].products;
if (data[i].category == list) {
for(z in productData){
for(x in productData[z][0]){
$(".content").append(productData[z][0][x])
}
$(".content").append('<br>')
}
}
}
})

Related

Looping through items in an object for google sheets

I am trying to loop through an array that is part of a JSON object from a page speed insights call to add all of the unused javascript Urls to a google sheet using the script editor.
Here is an example of the JSON object:
"audits": {
"unused-javascript": {
"id": "unused-javascript",
"title": "Remove unused JavaScript",
"description": "Remove unused JavaScript to reduce bytes consumed by network activity. [Learn more](https://web.dev/unused-javascript/).",
"score": 0.43,
"scoreDisplayMode": "numeric",
"numericValue": 1350,
"numericUnit": "millisecond",
"displayValue": "Potential savings of 231 KiB",
"details": {
"type": "opportunity",
"headings": [
{
"key": "url",
"valueType": "url",
"subItemsHeading": {
"key": "source",
"valueType": "code"
},
"label": "URL"
},
{
"key": "totalBytes",
"valueType": "bytes",
"subItemsHeading": {
"key": "sourceBytes"
},
"label": "Transfer Size"
},
{
"key": "wastedBytes",
"valueType": "bytes",
"subItemsHeading": {
"key": "sourceWastedBytes"
},
"label": "Potential Savings"
}
],
"items": [
{
"url": "https://connect.facebook.net/signals/config/1926350194273730?v=2.9.2=stable",
"totalBytes": 140229,
"wastedBytes": 108197,
"wastedPercent": 77.15757011763822
},
{
"url": "https://static.example.com/domain.us.modern.bundle.a02fef045566caf5d464.js",
"totalBytes": 306716,
"wastedBytes": 106243,
"wastedPercent": 34.63892414884589
},
{
"url": "https://www.googletagmanager.com/gtm.js?id=GTM-KZ",
"totalBytes": 127214,
"wastedBytes": 21845,
"wastedPercent": 17.17151000374831
}
],
"overallSavingsMs": 1350,
"overallSavingsBytes": 236285
}
},
I am attempting to loop through the "items" array within the "unused-javascript" object and get all of the urls to show in google sheets.
Here is the code I have within the script editor. When I run this, only one URL shows on the sheet. However, I am trying to get all of the URLs added to the sheet.
function pageSpeed(Url) {
var key = "AIzaSyAyHY";
var serviceUrl = "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=" + Url + "&key=" + key;
var array = [];
if (key == "YOUR_API_KEY")
return "Please enter your API key to the script";
var response = UrlFetchApp.fetch(serviceUrl);
if (response.getResponseCode() == 200) {
var content = JSON.parse(response.getContentText());
if ((content != null) && (content["lighthouseResult"] != null)) {
if (content["captchaResult"]) {
var timetointeractive = content["lighthouseResult"]["audits"]["interactive"]["displayValue"].slice(0, -2);
var firstcontentfulpaint = content["lighthouseResult"]["audits"]["first-contentful-paint"]["displayValue"].slice(0, -2);
var firstmeaningfulpaint = content["lighthouseResult"]["audits"]["first-meaningful-paint"]["displayValue"].slice(0, -2);
var speedindex = content["lighthouseResult"]["audits"]["speed-index"]["displayValue"].slice(0, -2);
var unusedJs = content["lighthouseResult"]["audits"]["unused-javascript"]["details"]["items"];
for (var i = 0; i < unusedJs.items.length; i++) {
var unusedUrl;
unusedUrl = unusedJs[i]["url"]
}
}
else {
var timetointeractive = "An error occured";
var firstcontentfulpaint = "An error occured";
var firstmeaningfulpaint = "An error occured";
var speedindex = "An error occured";
var unusedJs = "An error occured";
}
}
var currentDate = new Date().toJSON().slice(0, 10).replace(/-/g, '/');
array.push([timetointeractive, firstcontentfulpaint, firstmeaningfulpaint, speedindex, currentDate, "complete", unusedUrl]);
Utilities.sleep(1000);
return array;
}
}
Any and all help is appreciated!
You're on the right track.
Take a look below at my usage of Array.prototype.map. That's the simpler route.
Your for loop would work just as well IF you declared unusedUrl outside of (ie. before) the loop AND pushed to an existing array. As it is, there's an issue of scope, so unusedUrl is redeclared on every iteration, meaning you'll only assign the last iteration's value to unusedUrl.
Both solutions are below.
Using map
var content = {
lighthouseResult: {
audits: {
'unused-javascript': {
// Other stuff
details: {
// Other stuff
items: [
{
url:
'https://connect.facebook.net/signals/config/1926350194273730?v=2.9.2=stable',
totalBytes: 140229,
wastedBytes: 108197,
wastedPercent: 77.15757011763822,
},
{
url:
'https://static.example.com/domain.us.modern.bundle.a02fef045566caf5d464.js',
totalBytes: 306716,
wastedBytes: 106243,
wastedPercent: 34.63892414884589,
},
{
url: 'https://www.googletagmanager.com/gtm.js?id=GTM-KZ',
totalBytes: 127214,
wastedBytes: 21845,
wastedPercent: 17.17151000374831,
},
],
overallSavingsMs: 1350,
overallSavingsBytes: 236285,
},
},
},
},
}
var items = content.lighthouseResult.audits['unused-javascript'].details.items
var unusedUrls = items.map(item => item.url) // OR, using es6, items.map(({ url }) => url)
console.log(unusedUrls)
Using for
var items = content.lighthouseResult.audits['unused-javascript'].details.items
var unusedUrls = []
for (var i = 0; i < items.length; i++) {
unusedUrls.push(items[i]['url'])
}

Combine result from 2 api response into one array javascript

I have two different api response that I want to combine. First api response is like below
"Data1":[
{
"name": "First Officer",
"status": "ACTIVE",
"id": "111"
},
{
"name": "Second Officer",
"status": "DELETED",
"id": "222"
},
{
"name": "Third Officer",
"status": "ACTIVE",
"id": "333"
}
],
Data2[],
Data3[]
And the second response is to get latest position of the officer like below
[
{
"id": "111",
"latest_position": "Elm Street"
},
{
"id": "333",
"latest_position": "Newton Sr. Street"
}
]
I need to combine two response from API above to become one array like this
["111","First Officer","Elm Street"]
["333", "Third Officer","Newton Sr. Street"]
But what I get is data like
["333","Third Officer","Elm Street"]
["333", "Third Officer","Newton Sr. Street"]
Do you know where's the error from my code below
$.ajax({
url: api_url+'search?keyword='+keyword,
type: 'GET',
success: function(response) {
//console.log(response);
var keys = Object.keys(response.data);
for (var i = 0; i < keys.length; i++) {
var data = response.data[keys[i]]
for (var j = 0; j < data.length; j++) {
var name = data[j].name;
var sid = data[j].id;
$.ajax({
url: api_url+'positions?filter=%7B%22where%22%3A%7B%22user_id'+sid,
type: 'GET',
success: function(response2) {
//console.log(response);
for (var i = 0; i < response2.length; i++) {
var loc = response2[i].latest_position;
var obj = {
'id' : sid,
'name' : name,
'loc' : loc,
};
arrObj.push(obj);
}
}
})
}
}
console.log(arrObj);
Thank you
You can use Array.find to search the item from the second response by id.
Something like this:
const response1 = [{
"name": "First Officer",
"status": "ACTIVE",
"id": "111"
},
{
"name": "Second Officer",
"status": "DELETED",
"id": "222"
},
{
"name": "Third Officer",
"status": "ACTIVE",
"id": "333"
}
];
const response2 = [{
"id": "111",
"latest_position": "Elm Street"
},
{
"id": "333",
"latest_position": "Newton Sr. Street"
}
];
const merged = response2.map(item => {
const resp1Item = response1.find(r => r.id === item.id);
return { ...item,
...resp1Item
}
});
console.log(merged);
Your issue stems from the fact that the second $.ajax(...) call is asynchronous and by the time its success: callback gets to be evaluated, the fors are finished, so you're getting the last values from the arrays in all of the responses.
The solution is to create a closure around the second $.ajax(....) call, so it will make the definition context available at execution time.
Something around the lines of:
$.ajax({
url: api_url+'search?keyword='+keyword,
type: 'GET',
success: function(response) {
//console.log(response);
var keys = Object.keys(response.data);
for (var i = 0; i < keys.length; i++) {
var data = response.data[keys[i]]
for (var j = 0; j < data.length; j++) {
(function(data){
var name = data.name;
var sid = data.id;
$.ajax({
url: api_url+'positions?filter=%7B%22where%22%3A%7B%22user_id'+sid,
type: 'GET',
success: function(response2) {
//console.log(response);
for (var i = 0; i < response2.length; i++) {
var loc = response2[i].latest_position;
var obj = {
'id' : sid,
'name' : name,
'loc' : loc,
};
arrObj.push(obj);
}
}
})
})(data[j]);
}
}
console.log(arrObj);

option selects from json object on categories

Hi (sorry for my english), I have this script:
<script type="text/javascript">
$(document).ready(function() {
var idPlato = decodeURI(getUrlVars()["idPl"]);
var url = "http://localhost/plato-datos.php?idPla="+idPlato+"";
});
};
</script>
It brings me this json from my database:
[{"category":"first","name":"green","idP":"1", "count":3},
{"category":"first","name":"blue","idP":"2","count":5},
{"category":"sec","name":"peter","idP":"3", "count":3},
{"category":"sec","name":"james","idP":"4", "count":2,},
{"category":"third","name":"dog","idP":"5", "count":4}]
I need to create one radiobuton for every name and group by categores
I create a solution. Kinda ugly but it will work:
var data = [{
"category": "first",
"name": "green",
"idP": "1",
"count": 3
}, {
"category": "first",
"name": "blue",
"idP": "2",
"count": 5
}, {
"category": "sec",
"name": "peter",
"idP": "3",
"count": 3
}, {
"category": "sec",
"name": "james",
"idP": "4",
"count": 2,
}, {
"category": "third",
"name": "dog",
"idP": "5",
"count": 4
}];
var result = {};
data.map(a => {
if (result[a.category]) {
result[a.category].push(a.name);
} else {
result[a.category] = [a.name];
}
});
Object.keys(result).map(category => {
var select = document.createElement('select');
result[category].map(name => {
var option = document.createElement('option');
option.value = name;
option.text = name;
select.appendChild(option);
});
document.body.appendChild(select);
});
Im working with jquery mobile then i used autodividersSelector function for group by the category JSON object, and build a radiobuton for every name
<script type="text/javascript">
//catch the JSON from my database
$(document).ready(function() {
var idPla = decodeURI(getUrlVars()["idPl"]);
var urlAder =
"http://localhost/lista-adereso.php?idPla=" + idPla + "";
//print the radiobutons
$.getJSON(urlAder, function(resultado) {
var allfiles = '';
for (var i = 0, aderesos = null; i <
resultado.length; i++) {
aderesos = resultado[i];
allfiles +='<li><label><input type="radio" data-
status="' + aderesos.aderesoCatNom +'"
name="name" id="id" value="' +
aderesos.aderNombre +'">'+
aderesos.aderNombre + '</label></li>'; }
//Group by categories
$('#linkList')
.empty()
.append(allfiles)
.listview({
autodividers:true,
autodividersSelector: function ( li ) {
var out = li.find('input').data("status");
return out;
}
})
.listview("refresh");
});
});
</script>

How to get objects with same key values with comma separated

I have an array of objects , each object have key and value .I want if object have same keys then their values shoud be comma sepated of all the values of same key.
my html code:
<p ng-repeat="item in allOptions" class="item" id="{{item.id}}">
{{item.id}} <input type="checkbox" ng-change="sync(bool, item)" ng-model="bool" > {{item}} Selected: {{bool}}
</p>
and my controller code is :
$scope.allOptions = [
{
"id": "1",
"data": "one",
},
{
"id": "1",
"data": "two",
},
{
"id": "2",
"data": "three",
},
];
$scope.data = [
];
$scope.sync = function(bool, item){
if(bool){
// add item
$scope.data.push(item);
} else {
// remove item
for(var i=0 ; i < $scope.data.length; i++) {
if($scope.data[i] == item.id){
$scope.data.splice(i,1);
}
}
}
};
In data array i have objects ,if we select same key of objects (same id value )then i want
{
"id": "1",
"data": "one","two",
}
var myData = [{
"id": "1",
"data": "one",
},{
"id": "1",
"data": "two",
},{
"id": "2",
"data": "three",
}];
var output = [];
//Iterating each element of the myData
myData.forEach(o => {
//Checking the duplicate value and updating the data field
let temp = output.find(x => {
if (x && x.id === o.id) {
x.data += ", " + o.data;
return true;
}
});
if(!temp)
output.push(o);
});
console.log(output);
I think, easiest way to make it would be like:
z = [
{
"id": "1",
"data": "one",
},
{
"id": "1",
"data": "two",
},
{
"id": "2",
"data": "three",
},
];
And immediate code:
var result = {};
var groupedO = {};
for(a in z){
var id = z[a].id;
var data = z[a].data;
if(groupedO[id] && groupedO[id].data){
groupedO[id].data = groupedO[id].data + ',' + data;
} else {
groupedO[id] = {data:data};
}
}
for(ind in groupedO) {
var el = groupedO[ind];
if(el.data.split(',').length > 1) { // here we take only last those, where many datas grouped in
result.id = ind;
result.data = el.data;
}
}
After this, result will look like:
{ id: "1", data: "one,two" }
If you use jQuery, then you can use $.extend() function in this code if you don't want to put reference to the object item in array hash. This means that if you change the object item in array hash, then object item in array myData change too. To avoid this, use $.extend() function.
var myData = [
{
"id": "1",
"data": "one",
},
{
"id": "1",
"data": "two",
},
{
"id": "2",
"data": "three",
},
]; // this will be your input data
function filterData(collection) {
var hash = {};
var result = [];
collection.forEach(function (item) {
if (hash[item.id]) {
hash[item.id].data += ', ' + item.data;
}
else {
hash[item.id] = $.extend({}, item);
}
});
for (var i in hash) {
result.push(hash[i]);
}
return result;
}
var filteredData = filterData(myData); //your filtered data
You can do this in following manner:
var myData = [{
"id": "1",
"data": "one",
},
{
"id": "1",
"data": "two",
},
{
"id": "2",
"data": "three",
},
]; // this will be your input data
function filterData(collection) {
var hash = {};
var result = [];
collection.forEach(function(item) {
if (hash[item.id]) {
hash[item.id].data += ', ' + item.data;
} else {
hash[item.id] = item;
}
});
for (var i in hash) {
result.push(hash[i]);
}
return result;
}
console.log(
filterData(myData) //your filtered data
)

How to convert not nested JSON into nested HTML list in Javascript (or Coffeescript)?

I have some JSON data (simple array of objects) .
var input= [
{
"cat": "some",
"id": "0"
},
{
"cat": "some",
"id": "1"
},
{
"cat": "some/category",
"id": "2"
},
{
"cat": "some/category/sub",
"id": "3"
},
{
"cat": "some/other",
"id": "4"
},
{
"cat": "some/thing/different",
"id": "5"
},
{
"cat": "some/thing/different",
"id": "6"
},
{
"cat": "yet/another",
"id": "7"
}
]
I wanted to generate nested html list out of it based on categories:
some
0
1
category
2
sub
3
other
4
thing
different
5
6
yet
another
7
My first step was to create empty nested object using the function:
createNestedObject = function(base, names) {
var = 0;
var results = [];
while (i < names.length) {
base = base[names[i]] = base[names[i]] || {};
results.push(i++);
}
return results;
}
Next i populated it with data using by spliting "cat" strings and pushing "ids" in loop (ex. some.category.sub.ids.push(7))
The final result was:
var output =
{
"some": {
"ids": [
"0",
"1"
],
"category": {
"ids": [
"2"
],
"sub": {
"ids": [
"3"
]
}
},
"other": {
"ids": [
"4"
]
},
"thing": {
"different": {
"ids": [
"5",
"6"
]
}
},
"yet": {
"another": {
"ids": [
"7"
]
}
}
}
}
However, the structure somewhat problematic because i don't know the key names and the nesting depth in advance.
How to generate nested html list out of "output" or "input" data presented here?
How about this?
Example
JS
function ToHTML(input){
var html = '<ul>';
for(var key in input){
if(input[key] instanceof Array){
for(var i = 0; i < input[key].length; i++){
html += '<li>' + input[key][i] + '</li>';
}
}else{
html += '<li>' + key + ToHTML(input[key]) + '</li>';
}
}
html += '</ul>';
return html;
}
function ToNestedObject(input){
var i, y, len = input.length, parts, partsLen, obj = {}, prev;
for(i = 0; i < len; i++){
parts = input[i].cat.split('/');
partsLen = parts.length;
prev = obj;
for(y = 0; y < partsLen; y++){
prev[parts[y]] = prev[parts[y]] || {};
prev = prev[parts[y]];
}
if(!prev.ids){
prev.ids = [];
}
prev.ids.push(input[i].id);
}
return obj;
}
var input= [
{
"cat": "some",
"id": "0"
},
{
"cat": "some",
"id": "1"
},
{
"cat": "some/category",
"id": "2"
},
{
"cat": "some/category/sub",
"id": "3"
},
{
"cat": "some/other",
"id": "4"
},
{
"cat": "some/thing/different",
"id": "5"
},
{
"cat": "some/thing/different",
"id": "6"
},
{
"cat": "yet/another",
"id": "7"
}
];
document.getElementById('test').innerHTML = ToHTML(ToNestedObject(input));
HTML
<div id='test'></div>
The array is converted into object tree
function buildTreeObject ( input ) {
var obj = {}, n ;
input.forEach( function( v ){
var keys = v.cat.split('/'),
n = obj ;
keys.forEach( function( k ){
if ( !n[k]) {
n[k] = {};
}
n = n[k];
});
n[ v.id ] = v.id ;
});
return obj;
}
and we need a function to build html
function buildHtml( obj , ul ) {
for (i in obj) {
var li = document.createElement('li');
li.innerHTML = i;
ul.appendChild( li );
if ( typeof(obj[i])== "object" ) {
childUl = document.createElement('ul');
li.appendChild( childUl );
buildHtml(obj[i], childUl );
}
}
}
and make html use of input ( ie ur array )
var ul = document.createElement('ul'),
tree = buildTreeObject( input ) ;
buildHtml( tree ,ul );
var div = document.createElement('div');
div.appendChild( ul );
console.log( div.innerHTML );
Which prints desired ul li list
You can see result in http://jsfiddle.net/r3RWL/
Since you added jquery under tags, I have written solution to your problem in jQuery. Here is the code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
<div id="someDiv">
</div>
<script>
function prepareNestedStructure(input) {
var output = {},
catLevels,
currentCat;
$.each(input, function(index, catObject) {
catLevels = catObject.cat.split('/');
currentCat = output;
$.each(catLevels, function(index, name) {
if(!currentCat[name])
currentCat[name] = {};
currentCat = currentCat[name];
});
currentCat[catObject.id] = catObject.id;
});
return output;
}
function fillList(parentListEl, node) {
$.each(node, function(key, value) {
parentListEl.append('<li>' + key + '</li>');
if(jQuery.type(value) === 'object') {
var childEl = $('<ul></ul>');
parentListEl.append(childEl);
fillList(childEl, value);
}
});
}
var input= [
{
"cat": "some",
"id": "0"
},
{
"cat": "some",
"id": "1"
},
{
"cat": "some/category",
"id": "2"
},
{
"cat": "some/category/sub",
"id": "3"
},
{
"cat": "some/other",
"id": "4"
},
{
"cat": "some/thing/different",
"id": "5"
},
{
"cat": "some/thing/different",
"id": "6"
},
{
"cat": "yet/another",
"id": "7"
}
];
var output = prepareNestedStructure(input);
var ulDomElement = $('<ul></ul>');
fillList(ulDomElement, output);
$('#someDiv').append(ulDomElement);
</script>
</body>
</html>
what about this?
transform_deeply_nested_object = (dno) ->
result = ""
for key, value of dno
if value instanceof Array
result += "<ul>"
for elem in value
result += "<li>" + elem + "</li>\n"
result += "</ul>"
else
result += "<ul><li>" + key + "</li>"
result += transform_deeply_nested_object value
result += "</ul>"
Attention: Not tested!
Attention: This requires all leafs to be elements of an array always.

Categories

Resources