Using the following Sammy JS view, AmCharts and JSON, I'm trying to load more than one graph into the "insights" view:
this.get('#/insights', function (context) {
context.$element().html("<div id='chartdiv'></div>");
var chart = AmCharts.makeChart("chartdiv", {
"type": "pie",
"theme": "none",
"titles": [{
"text": "Header Text",
"size": 16
}],
"dataProvider": [{
"product": "Product 1",
"value": 23
}, {
"product": "Product 2",
"value": 56
}, {
"product": "Product 3",
"value": 21
}],
"titleField": "product",
"valueField": "value",
"labelRadius": 5,
"startEffect": "bounce",
"startDuration": 2,
"labelRadius": 15,
"radius": "22%",
"innerRadius": "60%",
"balloonText": "[[title]]<br><span style='font-size:14px'><b>[[value]]</b> ([[percents]]%)</span>"
//"labelText": "[[title]]"
});
});
I tried adding another div into:
context.$element().html("<div id='chartdiv'></div><div id='chartdiv2'></div>");
with associated amcharts data:
var chart = AmCharts.makeChart("chartdiv2", {
"type": "pie",
"theme": "none",
"titles": [{
"text": "Header Text",
"size": 16
}],
"dataProvider": [{
"product": "Product 1",
"value": 23
}, {
"product": "Product 2",
"value": 56
}, {
"product": "Product 3",
"value": 21
}],
"titleField": "product",
"valueField": "value",
"labelRadius": 5,
"startEffect": "bounce",
"startDuration": 2,
"labelRadius": 15,
"radius": "22%",
"innerRadius": "60%",
"balloonText": "[[title]]<br><span style='font-size:14px'><b>[[value]]</b> ([[percents]]%)</span>"
//"labelText": "[[title]]"
});
});
I can't seem to get the second graph to display.
I have used multiple piecharts this way, you can refer to my code below:-
/*
This code block i have used in php for dynamic data, you can ignore this block.
This is just to give you an idea about i am using data to populate the chart.
*/
$return['chartdata'] = $dataset;
$return['titlefield'] = $_POST['display_field'];
$return['valuefield'][] = 'count';
$return['valuefield'][] = 'value';
echo json_encode($return);
/*
Ends Here.
*/
/* Below code is what will help you. */
for (var i = 0; i < result.valuefield.length; i++) {
$('#charts_div').append("<div class='col-md-6'><div id='chartdiv"+(i+1)+"' style='width: 640px; height: 400px;'></div></div>");
var chart = new AmCharts.AmPieChart();
chart.pathToImages = gbl_js+"amcharts/images/";
chart.dataProvider = result.chartdata;
chart.titleField = result.titlefield;
chart.valueField = result.valuefield[i];
chart.legend = {
"markerType": "circle",
"position": "bottom",
"marginRight": 80,
"autoMargins": false,
"valueText": ""
};
chart.exportConfig = {
"menuTop": 0,
"menuItems": [{
"icon": gbl_js+'amcharts/images/export.png',
"items": [{
"title": 'JPG',
"format": 'jpg'
}, {
"title": 'PNG',
"format": 'png'
}, {
"title": 'SVG',
"format": 'svg'
}, {
"title": 'PDF',
"format": 'pdf'
}]
}
};
chart.write('chartdiv'+(i+1));
};
Related
I am attempting to toggle the opacity of a bar when it is clicked on utilizing the "dataPlotClick" event. I am able to change the opacity, but as soon as I move my mouse off of the bar the opacity changes back to the default.
NOTE: A similar question has been asked before on SO, but doesn't seem to have a valid answer.
How do I utilize the below dataPlotClick event to achieve this?
events: {
"dataPlotClick": function (evtObj, argObj) {
var i, plotItems;
plotItems = evtObj.sender.jsVars.hcObj.elements.plots[0].items;
plotItems[argObj.dataIndex].graphic.attr("fill-opacity", .2);
}
}
Fusion Chart:
FusionCharts.ready(function () {
var revenueChart = new FusionCharts({
type: 'column2d',
renderAt: 'chart-container',
width: '500',
height: '350',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Monthly revenue for last year",
"subCaption": "Harry's SuperMart",
"xAxisName": "Month",
"yAxisName": "Revenue (In USD)",
"numberPrefix": "$",
"paletteColors": "#0075c2",
"bgColor": "#ffffff",
"borderAlpha": "20",
"canvasBorderAlpha": "0",
"usePlotGradientColor": "0",
"plotBorderAlpha": "10",
"placevaluesInside": "1",
"rotatevalues": "1",
"valueFontColor": "#ffffff",
"showXAxisLine": "1",
"xAxisLineColor": "#999999",
"divlineColor": "#999999",
"divLineIsDashed": "1",
"showAlternateHGridColor": "0",
"subcaptionFontBold": "0",
"subcaptionFontSize": "14"
},
"data": [
{
"label": "Jan",
"value": "420000"
}, {
"label": "Feb",
"value": "810000"
}, {
"label": "Mar",
"value": "720000"
}, {
"label": "Apr",
"value": "550000"
}, {
"label": "May",
"value": "910000"
}, {
"label": "Jun",
"value": "510000"
}, {
"label": "Jul",
"value": "680000"
}, {
"label": "Aug",
"value": "620000"
}, {
"label": "Sep",
"value": "610000"
}, {
"label": "Oct",
"value": "490000"
}, {
"label": "Nov",
"value": "900000"
}, {
"label": "Dec",
"value": "730000"
}]
},
events: {
"dataPlotClick": function (evtObj, argObj) {
var i, plotItems, plotLength;
plotItems = evtObj.sender.jsVars.hcObj.elements.plots[0].items;
plotItems[argObj.dataIndex].graphic.attr("fill-opacity", .2);
}
}
}
}).render();
});
The alpha attribute need to set within the dataPlotClick FusionCharts API event for the particular data plot which has been clicked.
The particular data plot index could be found with the help of dataObj parameters dataIndex attribute within dataPlotClick FusionCharts API event.
Finally set the modified JSON structure with the help of FusionCharts setJSONData API method.
Please implement the below given code.
FusionCharts.ready(function () {
var topStores = new FusionCharts({
type: 'column2d',
renderAt: 'chart-container',
width: '400',
height: '300',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Monthly revenue for last year",
"subCaption": "Harry's SuperMart",
"xAxisName": "Month",
"yAxisName": "Revenue (In USD)",
"numberPrefix": "$",
"paletteColors": "#0075c2",
"bgColor": "#ffffff",
"borderAlpha": "20",
"canvasBorderAlpha": "0",
"usePlotGradientColor": "0",
"plotBorderAlpha": "10",
"placevaluesInside": "1",
"rotatevalues": "1",
"valueFontColor": "#ffffff",
"showXAxisLine": "1",
"xAxisLineColor": "#999999",
"divlineColor": "#999999",
"divLineIsDashed": "1",
"showAlternateHGridColor": "0",
"subcaptionFontBold": "0",
"subcaptionFontSize": "14"
},
"data": [{
"label": "Jan",
"value": "420000"
}, {
"label": "Feb",
"value": "810000"
}, {
"label": "Mar",
"value": "720000"
}, {
"label": "Apr",
"value": "550000"
}, {
"label": "May",
"value": "910000"
}, {
"label": "Jun",
"value": "510000"
}, {
"label": "Jul",
"value": "680000"
}, {
"label": "Aug",
"value": "620000"
}, {
"label": "Sep",
"value": "610000"
}, {
"label": "Oct",
"value": "490000"
}, {
"label": "Nov",
"value": "900000"
}, {
"label": "Dec",
"value": "730000"
}]
},
events: {
"dataPlotClick": function(evtObj, argObj) {
var plotNum= argObj.dataIndex;
var data =evtObj.sender.args.dataSource.data;
data[plotNum].alpha="10";
evtObj.sender.setJSONData(evtObj.sender.args.dataSource);
}
}
})
.render();
});
I have an api request that returns JSON data which is then used to populate an html table. I am able to populate the table with item.name ... I would like to add the metadata value for player.field but I have not been able to access it. Here is the JSON response:
{
"list": [
{
"id": 55,
"name": "0046GS (RMS03241708)",
"description": "S 12-7 M-S 10-9",
"uuid": "6f4b5bfd-6d17-4095-9e48-7b9313f7f8c6",
"previewPlayer": false,
"enabled": true,
"mac": "00-00-00-00-00-00",
"type": "CHROMEBOX",
"distributionServer": {
"id": 2,
"name": "Main",
"driver": "IP_P2P"
},
"playergroups": [
{
"id": 2,
"name": "GameStop",
"numberOfPlayers": 454
}
],
"playerDisplays": [
{
"id": 55,
"name": "Display 1",
"channel": {
"id": 53,
"name": "GameStop TV"
},
"screenCounter": 1
}
],
"requestLogs": false,
"downloadThreads": 1,
"unusedFilesCache": 24,
"planDeliveryMethod": "CONTENT_MANAGER_DIRECT",
"pollingInterval": 1,
"pollingUnit": "MINUTES",
"logLevel": "normal",
"metadataValue": [
{
"id": 12512,
"value": "true",
"playerMetadata": {
"id": 34,
"name": "Player.field",
"datatype": "BOOLEAN",
"valueType": "ANY",
"order": 4
}
},
{
"id": 1085,
"value": "77056",
"playerMetadata": {
"id": 31,
"name": "Player.ZipCode",
"datatype": "STRING",
"valueType": "ANY",
"order": 30
}
},
{
"id": 1071,
"value": "22:15",
"playerMetadata": {
"id": 10,
"name": "Player.ScreenOff_Wednesday",
"datatype": "STRING",
"valueType": "ANY",
"order": 12
}
}
],
"usedPairingKey": "HBVULW",
"active": "ACTIVE",
"lastModified": "2017-04-03 20:12:43",
"timezoneOffset": "0"
}
],
"offset": 0,
"count": 68
}
Here is the ajax request:
$.ajax({
type: 'GET',
url: "https://sampleserver.com:8080/ContentManager/api/rest/players?limit=1&offset=0&sort=name&filters=%7BplayerStatus%20:%20%7Bvalues:%5B'ACTIVE'%5D,%20comparator%20:%20'eq'%7D%7D",
dataType: "json",
success: function(data) {
$.each(data.list, function(i, item) {
var tr = $('<tr><td>'+item.name+'</td><td>'+some.JSONResponse+'</td></tr>').appendTo('#scalaapi');
});
}
});
I am stuck on how to specifically display the value for player.field ... "value": "true",
It feels like it should be simple, but my attempts have all been met with undefined.
Attempted if statement...
success: function(data) {
$.each(data.list, function(i, item) {
var tr = $('<tr><td>'+item.name+'</td><td class="val">...</td></tr>').appendTo('#scalaapi');
var bool = function(i,item) {if (item.metadataValue.id = '12512');
tr.find('.val').text(bool);};
});
}
});
I have facing problems with EXT js code to store data using Java.
Below is my code. Can one please help me.
Below is my NewCustomersVerify.js code:
var myHit = Ext.create('Ext.data.Store',{
fields:['Id','Name'],
data:[
{Id:'0',Name:'No'},
{Id:'1',Name:'Yes'}
]
});
var myRisk = Ext.create('Ext.data.Store',{
fields:['Id','Name'],
data:[
{Id:'0',Name:'Low'},
{Id:'1',Name:'High'}
]
});
Ext.define('Test.test.web.test.view.test.NewCustomersVerify', {
"xtype": "newCustomersVerify",
"items": [{
"xtype": "panel",
"items": [{
"xtype": "panel",
"items": [{
"xtype": "displayfield",
"fieldLabel": "Name :",
"margin": 5,
"value": "TEXT",
"name": "customerName",
"title": "Customer Name",
"itemId": "lnajnbi", "bind": "{customerName}"
},{
"xtype": "displayfield",
"fieldLabel": "Nationality :",
"margin": 5,
"value": "TEXT",
"name": "nationality",
"title": "Nationality",
"itemId": "lnbjnbi", "bind": "{nationality}"
},{
"xtype": "displayfield",
"fieldLabel": "UniqueId No :",
"margin": 5,
"value": "TEXT",
"name": "uniqueIdNo",
"title": "UniqueId No",
"itemId": "lncjnbi", "bind": "{uniqueIdNo}"
},{
"xtype": "hiddenfield",
"fieldLabel": "HiddenText",
"bindable": "contactId",
"margin": 5,
"name": "contactId",
"title": "HiddenText",
"itemId": "oidgafi",
"bind": "{contactId}"
},{
"xtype": "hiddenfield",
"fieldLabel": "HiddenText",
"bindable": "screeningId",
"margin": 5,
"name": "screeningId",
"title": "HiddenText",
"itemId": "didgafi",
"bind": "{screeningId}"
}],
"layout": "vbox",
"autoScroll": true,
"margin": 5,
"columnWidth": 0.5,
"itemId": "cieadni",
"dockedItems": []
}, {
"xtype": "panel",
"items": [
{
"xtype": "combo",
"fieldLabel": "Was there a verify hit?",
"name": "screeningHit",
"margin": 5,
"bindable": "screeningHit",
"title": "Was there a verify hit?",
"columnWidth": 0.5,
"width": "100",
"labelAlign": "left",
"itemId": "kbfmjgi",
displayField:'Name',
valueField:'Id',
queryMode:'local',
store: myHit,
}, {
"xtype": "combo",
"fieldLabel": "Country Risk (Nationality)",
"name": "countryRisk",
"margin": 5,
"bindable": "countryRisk",
"title": "Country Risk (Nationality)",
"columnWidth": 0.5,
"width": "100",
"labelAlign": "left",
"itemId": "kbgajgi",
displayField:'Name',
valueField:'Id',
queryMode:'local',
store: myRisk
}, {
"xtype": "combo",
"fieldLabel": "Occupation Risk",
"name": "occupationRisk",
"margin": 5,
"bindable": "occupationRisk",
"title": "Occupation Risk",
"columnWidth": 0.5,
"width": "100",
"labelAlign": "left",
"itemId": "kbaajgi",
displayField:'Name',
valueField:'Id',
queryMode:'local',
store: myRisk
}, {
"xtype" : "filefield",
"fieldLabel": "Upload evidence of verify (Screenshot from the verify portal)",
"msgTarget" : "side",
"allowBlank" : "false",
"buttonOnly" : "true",
"margin" : 5,
"name" : "uploadFile",
buttonConfig : {
"text" : "Upload",
"icon" : "images/cloud/upload.png",
},
listeners : {
change :"uploadFile"
}
}],
"layout": "vbox",
"autoScroll": true,
"margin": 5,
"columnWidth": 0.5,
"itemId": "nehbeki",
"dockedItems": []
}],
"layout": "column",
"autoScroll": true,
"border": true,
"margin": 5,
"itemId": "gjihcpi",
"dockedItems": [{
"xtype": "toolbar",
"dock": "bottom",
"ui": "footer",
"isToolBar": true,
"isDockedItem": true,
"items": [{
"xtype": "tbfill",
"itemId": "hajhegi"
},
/* {
"xtype": "button",
"name": "cancel",
"text": "Cancel",
"margin": 5,
"isResetButton": true,
"itemId": "bbkmkmi",
"listeners": {
"click": "oncancelclick"
}
},*/
{
"xtype": "button",
"name": "Confirm",
"text": "Confirm",
"margin": 5,
"itemId": "celbgji",
"listeners": {
"click": "onConfirmclick"
}
}],
"columnWidth": 0.5,
"itemId": "lfmepni",
"dockedItems": []
}]
}],
"border": true,
"autoScroll": false,
// "title": "New Customer Verify",
"margin": 5,
"itemId": "dinfmki",
"dockedItems": [],
"extend": "Ext.form.Panel",
"listeners": {
"afterrender": "onafterrender",
"scope": "controller"
},
"requires": ["Test.test.web.test.controller.test.NewCustomersVerifyController", "Test.test.shared.test.viewmodel.test.NewCustomersVerifyViewModel", "Test.test.shared.test.model.test.NewCustomersVerifyModel"],
"viewModel": "NewCustomersVerifyViewModel",
"controller": "NewCustomersVerifyController"
});
Below is my button onConfirmclick function call on NewCustomersVerifyContoller.js
onConfirmclick: function(me, e, eOpts) {
var jsonData = {};
jsonData.contactId = this.view.down('#oidgafi').getValue();
jsonData.screeningId = this.view.down('#didgafi').getValue();
jsonData.screeningHit = this.view.down('#kbfmjgi').getValue();
jsonData.countryHit = this.view.down('#kbgajgi').getValue();
jsonData.occupationHit = this.view.down('#kbaajgi').getValue();
var scope = this.getView();
Ext.MessageBox.show({
msg : 'Saving data...',
progressText : 'Saving...',
width : 300,
wait : true,
waitConfig : {
interval : 200
}
});
Ext.Ajax.request({
url: 'secure/NewCustomersVerifyServiceWS/respond',
method: 'POST',
sender: scope,
jsonData: jsonData,
me: me,
success: function(response, scope) {
Ext.MessageBox.hide();
responseData = Ext.JSON.decode(response.responseText);
Ext.Msg.alert('Server Response', responseData.response.message);
win = scope.sender.up();
win.reportViewController.queryCriteria.controller.filterData(win.searchButtonRef);
win.close();
},
failure: function(response, scope) {
Ext.MessageBox.hide();
responseData = Ext.JSON.decode(response.responseText);
Ext.Msg.alert('Server Response', responseData.response.message);
}
}, scope);
}
Below is the error i was getting on the browser console.
[E] Ext.JSON.decode(): You're trying to decode an invalid JSON String:
Apache Tomcat/8.0.21 - Error
reportH1
{font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;}
H2
{font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;}
H3
{font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;}
BODY
{font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;}
B
{font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P
{font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A
{color : black;}A.name {color : black;}.line {height: 1px;
background-color: #525D76; border: none;}
HTTP Status 400 - type Status reportmessage
description The request sent by the client was
syntactically incorrect.Apache
Tomcat/8.0.21
Error is on Ajax success or failure function. You are trying to decode invalid json which is passed from your controller (or middle layer server). You need to console the response before decode any string.
Just add console log before Ext.decode(). and post response here. That will solve your problem.
thank you for your support.
I have declared the variable occupationRisk as **occupationHit **.
That's the problem... Now its solved.
I want to pass the data value ui-grid.I need to pass $scope.ll value to ui-grid.If I copy the data and assigned $scope.ll=[{}] Id and statesum_totalcount are working well. I need to pass $scope.ll to grid
My data in array are as
{
"ID": "3",
"stat_sum": {
"totcount": 3
},
"zip_stats": [
{
"zip": "560045",
"count": 1
},
{
"zip": "567657",
"count": 2
}
],
"qual_stats": [
{
"count": 1,
"qualification": "B.E."
},
{
"count": 2,
"qualification": "BE"
}
],
"prof_stats": [
{
"count": 1,
"profession": "Doctor"
},
{
"count": 2,
"profession": "Software Engineer"
}
],
"city_stats": [
{
"city": null,
"count": 2
},
{
"city": "Bangalore",
"count": 1
}
],
"state_stats": [
{
"count": 1,
"state": "Karnataka"
},
{
"count": 2,
"state": "Kerala"
}
],
"stats_info": [
{
"acount": 3,
"answer": "fgdfgd",
"question": "comment-about-me-"
},
{
"acount": 1,
"answer": "one",
"question": "radio-answer-"
},
{
"acount": 2,
"answer": "two",
"question": "radio-answer-"
},
{
"acount": 3,
"answer": "t-shirt",
"question": "select-any-dress-for-me-[]"
},
{
"acount": 3,
"answer": "no",
"question": "say-yes-or-no-"
},
{
"acount": 3,
"answer": "2015-09-25",
"question": "select-your-b.date-"
},
{
"acount": 3,
"answer": "24",
"question": "select-your-age-"
},
{
"acount": 3,
"answer": "2",
"question": "type-number-"
},
{
"acount": 3,
"answer": "false",
"question": "select-true-or-false-"
}
]
}
In controller
$timeout(function () {
console.log($scope.ll); //works fine
$rootScope.showspinner = false;
$scope.gridOptionsComplex = {
enableFiltering: true,
showGridFooter: true,
showColumnFooter: true,
columnDefs: [
{name: 'ID', width: 100, enableCellEdit: false,},
{name: 'stat_sum.totcount', width: 100, enableCellEdit: false,},
{name: 'zip_stats.zip', width: 100, enableCellEdit: false,},
{name: 'zip_stats.count', width: 100, enableCellEdit: false,},
{name: 'qual_stats.qualification', width: 100, enableCellEdit: false,},
{name: 'qual_stats.count', width: 100, enableCellEdit: false,},
],
data:$scope.ll
};
$scope.$apply(function () {
$scope.aut = true;
});
}, 500, false);
The same kind of problem I faced ,I am giving an example code how to solve this
{
"result": {
"fileNames": [
"Book1 (2).csv",
"address_sample (3).csv",
"Book1.csv"
],
"ids": [
1,
2,
3
]
},
"responseSuccess": "success",
"responseError": null,
"responseInfo": null,
"responseWarning": null,
"responseCode": 0
}
I have output like above format and also I have to Integrate with these in to ui-grid .
example controller side code once the control reached success part I am getting the output as the format of above , so lets see how to integrate with ui-grid,
In my controller I have $scope.gridsOptions like
$scope.gridsOptions = {
columnDefs : [
{
field : 'field',
name : 'Id'
},
{
field : 'filename',
name : 'FileName'
}]
}
I assumed the control came to the success part .success(function()) what ever validate could you please validate then,
.success(function(data){
$scope.resultValues =[];
// Here My PD(Problem Domain says iterate based On `ids`)
for (var i = 0; i < data.result.ids.length; i++) {
// Im getting each ID in $scope.fileId variable
$scope.fileId = data.result.ids[i];
// Here Im getting each fieldNames in $scope.fileName variable
$scope.fileName = data.result.fileNames[i];
//Then I am pushing those values in to fieldId
$scope.resultValues.push({
field : $scope.fileId,
filename : $scope.fileName
});
}
ListData.fileIdValues = angular.copy($scope.resultValues);
// I am pointed those to $scope.gridsOptions.data
$scope.gridsOptions.data = ListData.fileIdValues;
})
Please Note ListData.fileIdValues in my code it is angular service variable this.fileIdValues ={}. For my Problem Domain I need these values so I stored it in serviceand use it where ever I want.
If I had the following code below, how would I display the usernames under likes? at the moment I use photo.images.low_resolution.url to show me the urk of the low resolution image but I can't figure out likes section.
{
"data": [{
"location": {
"id": "833",
"latitude": 37.77956816727314,
"longitude": -122.41387367248539,
"name": "Civic Center BART"
},
"comments": {
"count": 16,
"data": [ ... ]
},
"caption": null,
"link": "http://instagr.am/p/BXsFz/",
"likes": {
"count": 190,
"data": [{
"username": "shayne",
"full_name": "Shayne Sweeney",
"id": "20",
"profile_picture": "..."
}, {...subset of likers...}]
},
"created_time": "1296748524",
"images": {
"low_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/03/efc502667a554329b52d9a6bab35b24a_6.jpg",
"width": 306,
"height": 306
},
"thumbnail": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/03/efc502667a554329b52d9a6bab35b24a_5.jpg",
"width": 150,
"height": 150
},
"standard_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/03/efc502667a554329b52d9a6bab35b24a_7.jpg",
"width": 612,
"height": 612
}
},
"type": "image",
"filter": "Earlybird",
"tags": [],
"id": "22987123",
"user": {
"username": "kevin",
"full_name": "Kevin S",
"profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_3_75sq_1295574122.jpg",
"id": "3"
}
},
...]
}
See this jsFiddle. Note the second entry has no data.
Please:
//photo = your object
//Make sure to remove empty objects({...}) as in your code example.
for (var i = 0; i < photo.data.length; i++) {
var photoData = photo.data[i];
for (var x = 0; x < photoData.likes.data.length; x++) {
//Do what ever you want with the like's user...
var likeData = photoData.likes.data[x];
alert(likeData.username);
}
}
And next time use console.log to navigate through your objects: