How to pull out relationships in nested JS object? - javascript

I have a nested (up to 21 deep) JSON in the following format:
{
"name": "Unknown Wife",
"id": 341,
"house": "Tyrell",
"gender": "Female",
"partnerId": 340,
"hasParnter": true,
"noParent": true,
"children": [{
"name": "Olymer",
"id": 342,
"house": "Tyrell",
"gender": "Male",
"partnerId": 343,
"hasParnter": true,
"isSource": true
}, {
"name": "Lysa Meadows",
"id": 343,
"house": "Tyrell",
"gender": "Female",
"partnerId": 342,
"hasParnter": true,
"noParent": true,
"children": [{
"name": "Raymund",
"id": 344,
"house": "Tyrell",
"gender": "Male",
"isSource": true
}, {
"name": "Rickard",
"id": 345,
"house": "Tyrell",
"gender": "Male",
"isSource": true
}, {
"name": "Megga",
"id": 346,
"house": "Tyrell",
"gender": "Female",
"isSource": true
}]
I am trying to transform this data into the format
{name: "someName", children:["all","children","deeper","in","object"]},
So presumably, highest level members of the original object would have the longest array of children. Within a single lineage, this would reduce as you worked deeper down the family tree.
What is the best route for recursively working into the family tree and returning to a new object in the format directly above?

You should use Reduce recursively.
var person = {"name":"Unknown Wife","id":341,"house":"Tyrell","gender":"Female","partnerId":340,"hasParnter":true,"noParent":true,"children":[{"name":"Olymer","id":342,"house":"Tyrell","gender":"Male","partnerId":343,"hasParnter":true,"isSource":true},{"name":"Lysa Meadows","id":343,"house":"Tyrell","gender":"Female","partnerId":342,"hasParnter":true,"noParent":true,"children":[{"name":"Raymund","id":344,"house":"Tyrell","gender":"Male","isSource":true},{"name":"Rickard","id":345,"house":"Tyrell","gender":"Male","isSource":true},{"name":"Megga","id":346,"house":"Tyrell","gender":"Female","isSource":true}]}]};
function printAll(p1) {
print(p1);
if (p1.children) {
p1.children.forEach(c => printAll(c))
}
}
function print(p1) {
console.log({person: p1.name, descendents: (p1.children || []).reduce(GetChildren, [])});
}
function GetChildren(children, child) {
return children.concat(child.name).concat((child.children || []).reduce(GetChildren, []));
}
<button onclick="print(person)">Print main person</button>
<button onclick="printAll(person)">Print for all</button>

It's not very clear to me from your question what's the desired result exactly but it's definitely recursion what you are after, I will assume you want something like this
obj={ "name": "Unknown Wife", "id": 341, "house": "Tyrell", "gender": "Female", "partnerId": 340, "hasParnter": true, "noParent": true, "children": [{ "name": "Olymer", "id": 342, "house": "Tyrell", "gender": "Male", "partnerId": 343, "hasParnter": true, "isSource": true }, { "name": "Lysa Meadows", "id": 343, "house": "Tyrell", "gender": "Female", "partnerId": 342, "hasParnter": true, "noParent": true, "children": [{ "name": "Raymund", "id": 344, "house": "Tyrell", "gender": "Male", "isSource": true }, { "name": "Rickard", "id": 345, "house": "Tyrell", "gender": "Male", "isSource": true }, { "name": "Megga", "id": 346, "house": "Tyrell", "gender": "Female", "isSource": true }] }] }
results=[]
children=[]
function myfunc(myObj){
if(myObj.name){
myObj.children.forEach(o=>{
if(!o.children){
children.push(o)
results.push({name:myObj.name,children:children})
}
else {
children.push({name:o.name,id:o.id,house:o.house,gender:o.gender,partnerId:o.partnerId,hasParnter:o.hasParnter,noParent:o.noParent})}
})
}
if(Array.isArray(myObj.children)){
for(let i=0; i<myObj.children.length; i++){
if(!myObj.children[i].children) continue
if(myObj.children[i].name) results.push({name:myObj.children[i].name,children:[myObj.children[i].children]})
else myfunc(myObj.children[i])
}
}
}
myfunc(obj)
console.log(results)

Related

Convert an object to 3d array

I am new to node.js and javascript. I am trying to build a rest API.
For a specific purpose, I need to convert an object to 3d array.
I tried running for, foreach loop but it is not providing what I am trying to achieve.
My object looks like this.
"data": [
{
"id": 15184,
"badge_id": "330886",
"name": "Rukmani J. Solanki",
"gender": "Female",
"type": "PF",
"department": "Sales",
"checkin": "2021-09-24T08:52:44.000Z",
"checkout": "2021-09-24T08:57:45.000Z",
"hours": "00:05"
},
{
"id": 15185,
"badge_id": "440886",
"name": "Jairam J. Solanki",
"gender": "Male",
"type": "PM",
"department": "Sales",
"checkin": "2021-09-24T09:28:32.000Z",
"checkout": null,
"hours": null
}
]
And I want something like this
{
"onfield": [
{
"key": "Sales",
"data": {
"PM": [
{
"name": "Gokuldas S. Sundrani",
"badge_id": "441101",
"gender": "Male",
"checkIn": "2021-09-24 06:04:18",
"checkOut": null,
"hours": "NoCheckOut"
},
{
"name": "Satnamsingh M. Chhabra",
"badge_id": "551249",
"gender": "Male",
"checkIn": "2021-09-24 06:47:31",
"checkOut": "2021-09-24 08:32:00",
"hours": "1.7 Hours"
},
{
"name": "Praveen N. Jethwani",
"badge_id": "771328",
"gender": "Male",
"checkIn": "2021-09-24 07:14:11",
"checkOut": "2021-09-24 08:29:34",
"hours": "1.3 Hours"
},
{
"name": "Satnamsingh M. Chhabra",
"badge_id": "88249",
"gender": "Male",
"checkIn": "2021-09-24 08:32:00",
"checkOut": null,
"hours": "NoCheckOut"
},
{
"name": "Arjundas D. Chhabra",
"badge_id": "661248",
"gender": "Male",
"checkIn": "2021-09-24 10:19:22",
"checkOut": "2021-09-24 18:38:32",
"hours": "8.3 Hours"
},
{
"name": "Parmanand C. Lalwani",
"badge_id": "8651418",
"gender": "Male",
"checkIn": "2021-09-24 14:51:08",
"checkOut": "2021-09-24 17:39:27",
"hours": "2.8 Hours"
},
{
"name": "Dhanalal G. Chouhan",
"badge_id": "5501392",
"gender": "Male",
"checkIn": "2021-09-24 14:58:46",
"checkOut": "2021-09-24 18:20:50",
"hours": "3.4 Hours"
}
],
"PF": [
{
"name": "Baljeetkaur S. Chhabra",
"badge_id": "501993",
"gender": "Female",
"checkIn": "2021-09-24 06:47:48",
"checkOut": "2021-09-24 08:32:12",
"hours": "1.7 Hours"
},
{
"name": "Baljeetkaur S. Chhabra",
"badge_id": "801993",
"gender": "Female",
"checkIn": "2021-09-24 08:32:12",
"checkOut": null,
"hours": "NoCheckOut"
}
],
"OM": [
{
"name": "Yadvendra Bhati",
"badge_id": "2255454",
"gender": "male",
"checkIn": "2021-09-24 13:38:37",
"checkOut": "2021-09-24 17:24:11",
"hours": "3.8 Hours"
}
],
"OF": [
{
"name": "Yashoda Bhati",
"badge_id": "223F0029",
"gender": "Female",
"checkIn": "2021-09-24 13:38:44",
"checkOut": "2021-09-24 17:24:25",
"hours": "3.8 Hours"
}
]
}
}
]
}
How can this be done?
I will be really grateful to you for your help.
I have googled and searched StackOverflow but did not find anything which deals with this kind of problem.
Thank You
Although I totally agree with Juan Mendes, here is a tip in order for you to be able to accomplish this. You may get an intermediate form for your data as this one:
{
"onfield": [
{
"key": "dept1",
"data": {
"PM": [
{
"id": 123,
"badge_id": "1231",
"name": "name1",
"gender": "Male"
}
]
}
},
{
"key": "dept2",
"data": {
"PF": [
{
"id": 124,
"badge_id": "1232",
"name": "name2",
"gender": "Female"
}
]
}
},
{
"key": "dept1",
"data": {
"PM": [
{
"id": 125,
"badge_id": "1233",
"name": "name3",
"gender": "Male",
"type": "PM",
"dept": "dept1"
}
]
}
}
]
}
Perhaps transforming your source data to this one is easier. And getting to your target from here will be just a matter of merging arrays of the same type.
Do not hesitate to ask if this keeps being difficult. But as said, please try to solve this yourself, that's the way you are going to learn.
let data = [{ "id": 123, "badge_id": "1231", "name": "name1", "gender": "Male", "type": "PM", "dept": "dept1" }, { "id": 124, "badge_id": "1232", "name": "name2", "gender": "Female", "type": "PF", "dept": "dept2" }, { "id": 125, "badge_id": "1233", "name": "name3", "gender": "Male", "type": "PM", "dept": "dept1" }];
let Report = []
data.forEach((item) => {
let obj = Report.find(v => v.dept == item.dept);
if (!obj) Report.push(obj = {
dept: item.dept,
type: {}
});
obj.type[item.type] ??= [];
obj.type[item.type].push({
id: item.id,
badge_id: item.badge_id,
name: item.name,
gender: item.gender,
});
})
console.log(Report)
Here's Something i think is more feasible than your result .. Checkout
let myObject = {
"data": [ {
"id": 123,
"badge_id": "1231",
"name": "name1",
"gender": "Male",
"type": "PM",
"dept": "dept1"
},
{
"id": 124,
"badge_id": "1232",
"name": "name2",
"gender": "Female",
"type": "PF",
"dept": "dept2"
},
{
"id": 125,
"badge_id": "1233",
"name": "name3",
"gender": "Male",
"type": "PM",
"dept": "dept1"
}]
}
function generateReport(object) {
let obj = {
"Report": []
};
let types = [];
object.data.forEach(arr =>{
if(!types.includes(arr.type)){
types.push(arr.type);
}
});
types.forEach(type =>{
obj.Report.push({
type : type,
users : object.data.filter(arr=>{ let a = arr.type == type;
if(a){
delete arr.type;
}
return a;
})
});
});
return obj;
}
myObject = generateReport(myObject);
console.log(myObject)
You oculd take the wanted grouping keys in an array and destructure the object to remove this keys from the object.
Every key takes it own nested object structure.
const
data = [{ id: 123, badge_id: "1231", name: "name1", gender: "Male", type: "PM", dept: "dept1" }, { id: 124, badge_id: "1232", name: "name2", gender: "Female", type: "PF", dept: "dept2" }, { id: 125, badge_id: "1233", name: "name3", gender: "Male", type: "PM", dept: "dept1" }],
keys = ['dept', 'type'],
result = data
.reduce((r, o) => {
keys
.reduce(function (t, k) {
let key;
({ [k]: key, ...o } = o);
if (!t[key]) t._.push({ [k]: key, data: (t[key] = { _: [] })._ });
return t[key];
}, r)
._
.push(o);
return r;
}, { _: [] })
._;
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Nested Objects in JSON Array return values for onlye first item

I have an array of employees. when i map trough this array and retrieve values of objects using dot notation everything works fine for top level objects but sub objects return value for employee.jobtitle.jobdesc of only first object.
All remaining objects records for employee.jobtitle.jobdesc are empty. Below is array. i am using map.employees method to iterate through array and rendering output using ( {employee.id} {employee.firstname} {employee.lastname} and {employee.jobtitle.jobdesc}. Why nested objects are only returning output for only first object e.g. Edward whereas for other Salesman it is not returning anything.
[
{
"id": 1,
"firstname": "John",
"lastname": "Bob",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 1,
"jobdesc": "General Manager"
}
},
{
"id": 2,
"firstname": "Edward",
"lastname": "Rick",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 2,
"jobdesc": "Salesman"
}
},
{
"id": 3,
"firstname": "Mike",
"lastname": "Arther",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 3,
"jobdesc": "Sales"
}
},
{
"id": 4,
"firstname": "Nick",
"lastname": "Johns",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 4,
"jobdesc": "Salesman"
}
}
]
Here is a solution that uses Array map(). You can read more about it in the link below.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
const employees = [
{
"id": 1,
"firstname": "John",
"lastname": "Bob",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 1,
"jobdesc": "General Manager"
}
},
{
"id": 2,
"firstname": "Edward",
"lastname": "Rick",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 2,
"jobdesc": "Salesman"
}
},
{
"id": 3,
"firstname": "Mike",
"lastname": "Arther",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 3,
"jobdesc": "Sales"
}
},
{
"id": 4,
"firstname": "Nick",
"lastname": "Johns",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 4,
"jobdesc": "Salesman"
}
}
];
const allJobs = employees
.map(employee => employee.jobtitle.jobdesc);
console.log(allJobs);
React example
const employees = [{
"id": 1,
"firstname": "John",
"lastname": "Bob",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 1,
"jobdesc": "General Manager"
}
},
{
"id": 2,
"firstname": "Edward",
"lastname": "Rick",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 2,
"jobdesc": "Salesman"
}
},
{
"id": 3,
"firstname": "Mike",
"lastname": "Arther",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 3,
"jobdesc": "Sales"
}
},
{
"id": 4,
"firstname": "Nick",
"lastname": "Johns",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 4,
"jobdesc": "Salesman"
}
}
];
const PersonList = () => {
return employees.map(employee => (
<div key={employee.id}>
<h2>{employee.firstname} {employee.lastname}</h2>
<h3>{employee.jobtitle.jobdesc}</h3>
<hr />
</div>
))
}
ReactDOM.render(<PersonList />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app">
</div>
Vanilla JavaScript example
const employees = [{
"id": 1,
"firstname": "John",
"lastname": "Bob",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 1,
"jobdesc": "General Manager"
}
},
{
"id": 2,
"firstname": "Edward",
"lastname": "Rick",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 2,
"jobdesc": "Salesman"
}
},
{
"id": 3,
"firstname": "Mike",
"lastname": "Arther",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 3,
"jobdesc": "Sales"
}
},
{
"id": 4,
"firstname": "Nick",
"lastname": "Johns",
"gender": "Male",
"nationalId": 1212121212,
"jobtitle": {
"id": 4,
"jobdesc": "Salesman"
}
}
];
const appDiv = document.getElementById('app');
employees.forEach(employee => {
const empDiv = document.createElement('div');
empDiv.setAttribute('id', employee.id);
const empH2 = document.createElement('h2');
empH2.innerText = `${employee.firstname} ${employee.lastname}`;
empDiv.append(empH2);
const empH3 = document.createElement('h3');
empH3.innerText = employee.jobtitle.jobdesc;
empDiv.append(empH3);
const divider = document.createElement('hr');
empDiv.append(divider);
appDiv.append(empDiv);
});
<div id="app">
</div>

How to get a specific object from whole object?

I am trying to get specific object from a whole object below is the example
by using localStorage.getItem('shop/elasticCache/shirt');
I get below data
{"description":"Tech Shirt","configurable_options":[{"attribute_id":80,"values":[{"value_index":"5176","label":"RUST"}],"label":"Color","attribute_code":"color"},{"attribute_id":125,"values":[{"value_index":"2898","label":"Small"},{"value_index":"2901","label":"Medium"},{"value_index":"2904","label":"Large"}],"label":"Size","attribute_code":"size"}],"tsk":1594790209,"size_options":[2898,2901,2904],"regular_price":28,"final_price":null,"price":28,"color_options":[5176],"special_from_date":null,"id":250659,"category":[{"category_id":2,"name":"Default Category","position":1},{"category_id":3,"name":"Clothing","position":14985},{"category_id":30,"name":"Bottoms","position":798},{"category_id":58,"name":"Leggings","position":1},{"category_id":1130,"name":"Char Test Category","position":30}],"sku":"S155551","product_links":[{"link_type":"related","linked_product_sku":null,"linked_product_type":null,"position":0,"sku":"P100031"},{"link_type":"related","linked_product_sku":null,"linked_product_type":null,"position":0,"sku":"P100031"}
I am trying to get
{"category_id":3,"name":"Clothing","position":14985},{"category_id":30,"name":"Bottoms","position":798},{"category_id":58,"name":"Leggings","position":1},{"category_id":1130,"name":"Char Test Category","position":30}]
Is their any way it can be done ?
const {category} = JSON.parse(localStorage.getItem('shop/elasticCache/shirt');)
or
const {category } = {
"description": "Tech Shirt",
"configurable_options": [{
"attribute_id": 80,
"values": [{
"value_index": "5176",
"label": "RUST"
}],
"label": "Color",
"attribute_code": "color"
}, {
"attribute_id": 125,
"values": [{
"value_index": "2898",
"label": "Small"
}, {
"value_index": "2901",
"label": "Medium"
}, {
"value_index": "2904",
"label": "Large"
}],
"label": "Size",
"attribute_code": "size"
}],
"tsk": 1594790209,
"size_options": [2898, 2901, 2904],
"regular_price": 28,
"final_price": null,
"price": 28,
"color_options": [5176],
"special_from_date": null,
"id": 250659,
"category": [{
"category_id": 2,
"name": "Default Category",
"position": 1
}, {
"category_id": 3,
"name": "Clothing",
"position": 14985
}, {
"category_id": 30,
"name": "Bottoms",
"position": 798
}, {
"category_id": 58,
"name": "Leggings",
"position": 1
}, {
"category_id": 1130,
"name": "Char Test Category",
"position": 30
}],
"sku": "S155551",
"product_links": [{
"link_type": "related",
"linked_product_sku": null,
"linked_product_type": null,
"position": 0,
"sku": "P100031"
}, {
"link_type": "related",
"linked_product_sku": null,
"linked_product_type": null,
"position": 0,
"sku": "P100031"
}]
}
objc={"description":"Tech Shirt","configurable_options":
[{"attribute_id":80,"values":[{"value_index":"5176","label":"RUST"}],
"label":"Color","attribute_code":"color"},
{"attribute_id":125,"values":[{"value_index":"2898","label":"Small"}
,{"value_index":"2901","label":"Medium"},
{"value_index":"2904","label":"Large"}],
"label":"Size","attribute_code":"size"}],
"tsk":1594790209,"size_options":[2898,2901,2904]
,"regular_price":28,"final_price":null,"price":28,
"color_options":[5176],"special_from_date":null,"id":250659,
"category":[{"category_id":2,"name":"Default Category","position":1},
{"category_id":3,"name":"Clothing","position":14985},
{"category_id":30,"name":"Bottoms","position":798},
{"category_id":58,"name":"Leggings","position":1},
{"category_id":1130,"name":"Char Test Category","position":30}],
"sku":"S155551","product_links":
[{"link_type":"related","linked_product_sku":null,"linked_product_type":null,"position":0,"sku":"P100031"},
{"link_type":"related","linked_product_sku":null,"linked_product_type":null,"position":0,"sku":"P100031"}]
}
res = objc["category"]
res.shift()
console.log(res)
$(document).ready(function () {
var jsonObj = {
"description": "Tech Shirt",
"configurable_options": [{
"attribute_id": 80,
"values": [{
"value_index": "5176",
"label": "RUST"
}],
"label": "Color",
"attribute_code": "color"
}, {
"attribute_id": 125,
"values": [{
"value_index": "2898",
"label": "Small"
}, {
"value_index": "2901",
"label": "Medium"
}, {
"value_index": "2904",
"label": "Large"
}],
"label": "Size",
"attribute_code": "size"
}],
"tsk": 1594790209,
"size_options": [2898, 2901, 2904],
"regular_price": 28,
"final_price": null,
"price": 28,
"color_options": [5176],
"special_from_date": null,
"id": 250659,
"category": [{
"category_id": 2,
"name": "Default Category",
"position": 1
}, {
"category_id": 3,
"name": "Clothing",
"position": 14985
}, {
"category_id": 30,
"name": "Bottoms",
"position": 798
}, {
"category_id": 58,
"name": "Leggings",
"position": 1
}, {
"category_id": 1130,
"name": "Char Test Category",
"position": 30
}],
"sku": "S155551",
"product_links": [{
"link_type": "related",
"linked_product_sku": null,
"linked_product_type": null,
"position": 0,
"sku": "P100031"
}, {
"link_type": "related",
"linked_product_sku": null,
"linked_product_type": null,
"position": 0,
"sku": "P100031"
}]
};
for(var i = 1; i < jsonObj.category.length; i++){
console.log(jsonObj.category[i]);
}
});
You can iterate through the entire object and can get the required values. The above code gives the values of category from index 1.

How do I filter an object based on multiple nested criteria?

I've got the following object and I'm trying to filter and return players from both groups based on multiple criteria such as "show me all players where franchise = Marvel, and power= flight" but I'm getting hung up in multiple levels of filtering.
I was looking at this answer but it doesn't seem to fit my scenario: JavaScript - Filter object based on multiple values
I can get results if I iterate over the groups but there are potentially lots of groups and I didn't want to get hung up in that. Is that the best way, though?
oPlayers.players.groups.filter(function(hero){return hero.Id == 1})
oPlayers = {
"players": {
"groups": [
{
"Id": 1,
"hero": [
{
"Id": 1,
"name": "Batman",
"franchise": "DC",
"gender": "Male",
"powers": [{"power":"stealth"},{"power":"intelligence"},{"power":"weaponry"}]
},
{
"Id": 2,
"name": "Ironman",
"franchise": "Marvel",
"gender": "Male",
"powers": [{"power":"flight"},{"power":"intelligence"},{"power":"weaponry"}]
},
{
"Id": 3,
"name": "Supergirl",
"franchise": "DC",
"gender": "Female",
"powers": [{"power":"flight"},{"power":"strength"},{"power":"speed"}]
},
{
"Id": 4,
"name": "Valkyrie",
"franchise": "Marvel",
"gender": "Female",
"powers": [{"power":"flight"},{"power":"intelligence"},{"power":"strength"}]
}
]
},
{
"Id": 2,
"hero": [
{
"Id": 1,
"name": "Batwoman",
"franchise": "DC",
"gender": "Female",
"powers": [{"power":"stealth"},{"power":"intelligence"},{"power":"weaponry"}]
},
{
"Id": 2,
"name": "IronPepper",
"franchise": "Marvel",
"gender": "Female",
"powers": [{"power":"flight"},{"power":"intelligence"},{"power":"weaponry"}]
},
{
"Id": 3,
"name": "Superman",
"franchise": "DC",
"gender": "Male",
"powers": [{"power":"flight"},{"power":"strength"},{"power":"speed"}]
},
{
"Id": 4,
"name": "Thor",
"franchise": "Marvel",
"gender": "Male",
"powers": [{"power":"flight"},{"power":"intelligence"},{"power":"strength"}]
}
]
}
]
}
}
You can first use flatMap to get a single list of all players. Then, given that your criteria is specified as an object, you can filter players based on whether every property specified in criteria matches properties of a player:
function filter(players, criteria) {
return players.players.groups.flatMap(({Id, hero}) =>
hero.filter(p =>
Object.entries(criteria).every(([k, v]) => {
if (k === 'power') return p.powers.some(({power}) => power === v);
return p[k] === v;
}))
.map(p => ({groupId: Id, ...p})));
}
const oPlayers = {
"players": {
"groups": [{
"Id": 1,
"hero": [{
"Id": 1,
"name": "Batman",
"franchise": "DC",
"gender": "Male",
"powers": [{
"power": "stealth"
}, {
"power": "intelligence"
}, {
"power": "weaponry"
}]
},
{
"Id": 2,
"name": "Ironman",
"franchise": "Marvel",
"gender": "Male",
"powers": [{
"power": "flight"
}, {
"power": "intelligence"
}, {
"power": "weaponry"
}]
},
{
"Id": 3,
"name": "Supergirl",
"franchise": "DC",
"gender": "Female",
"powers": [{
"power": "flight"
}, {
"power": "strength"
}, {
"power": "speed"
}]
},
{
"Id": 4,
"name": "Valkyrie",
"franchise": "Marvel",
"gender": "Female",
"powers": [{
"power": "flight"
}, {
"power": "intelligence"
}, {
"power": "strength"
}]
}
]
},
{
"Id": 2,
"hero": [{
"Id": 1,
"name": "Batwoman",
"franchise": "DC",
"gender": "Female",
"powers": [{
"power": "stealth"
}, {
"power": "intelligence"
}, {
"power": "weaponry"
}]
},
{
"Id": 2,
"name": "IronPepper",
"franchise": "Marvel",
"gender": "Female",
"powers": [{
"power": "flight"
}, {
"power": "intelligence"
}, {
"power": "weaponry"
}]
},
{
"Id": 3,
"name": "Superman",
"franchise": "DC",
"gender": "Male",
"powers": [{
"power": "flight"
}, {
"power": "strength"
}, {
"power": "speed"
}]
},
{
"Id": 4,
"name": "Thor",
"franchise": "Marvel",
"gender": "Male",
"powers": [{
"power": "flight"
}, {
"power": "intelligence"
}, {
"power": "strength"
}]
}
]
}
]
}
};
console.log(filter(oPlayers, {gender: 'Male', franchise: 'Marvel'}));
console.log(filter(oPlayers, {gender: 'Female', power: 'flight'}));

show additional data properties on mouseover in dc.js

I would like to display additional data labels and values (other than x-axis and y-axis) on mouseover in dc.js. Below are data and the charting code.
var people = [
{
"id": 1,
"name": "Damaris",
"gender": "Female",
"DOB": "1973-02-18",
"MaritalStatus": "false",
"CreditCardType": "visa-electron"
},
{
"id": 2,
"name": "Barbe",
"gender": "Female",
"DOB": "1969-04-10",
"MaritalStatus": "true",
"CreditCardType": "americanexpress"
},
{
"id": 3,
"name": "Belia",
"gender": "Female",
"DOB": "1960-04-16",
"MaritalStatus": "false",
"CreditCardType": "maestro"
},
{
"id": 4,
"name": "Leoline",
"gender": "Female",
"DOB": "1995-01-19",
"MaritalStatus": "true",
"CreditCardType": "bankcard"
},
{
"id": 5,
"name": "Valentine",
"gender": "Female",
"DOB": "1992-04-16",
"MaritalStatus": "false",
"CreditCardType": ""
},
{
"id": 6,
"name": "Rosanne",
"gender": "Female",
"DOB": "1985-01-05",
"MaritalStatus": "true",
"CreditCardType": "bankcard"
},
{
"id": 7,
"name": "Shalna",
"gender": "Female",
"DOB": "1956-11-01",
"MaritalStatus": "false",
"CreditCardType": "jcb"
},
{
"id": 8,
"name": "Mordy",
"gender": "Male",
"DOB": "1990-03-27",
"MaritalStatus": "true",
"CreditCardType": "china-unionpay"
},
{
"id": 9,
"name": "Tristan",
"gender": "Male",
"DOB": "1998-10-05",
"MaritalStatus": "true",
"CreditCardType": ""
},
{
"id": 10,
"name": "Alphonso",
"gender": "Male",
"DOB": "1992-08-10",
"MaritalStatus": "false",
"CreditCardType": "mastercard"
},
{
"id": 11,
"name": "Hirsch",
"gender": "Male",
"DOB": "1973-02-13",
"MaritalStatus": "false",
"CreditCardType": ""
},
{
"id": 12,
"name": "Kirstyn",
"gender": "Female",
"DOB": "1989-06-28",
"MaritalStatus": "false",
"CreditCardType": "bankcard"
},
{
"id": 13,
"name": "Benson",
"gender": "Male",
"DOB": "1959-10-19",
"MaritalStatus": "true",
"CreditCardType": "switch"
},
{
"id": 14,
"name": "Florry",
"gender": "Female",
"DOB": "1993-11-11",
"MaritalStatus": "true",
"CreditCardType": "diners-club-international"
},
{
"id": 15,
"name": "Jenine",
"gender": "Female",
"DOB": "1957-02-16",
"MaritalStatus": "false",
"CreditCardType": "diners-club-enroute"
},
{
"id": 16,
"name": "Hortense",
"gender": "Female",
"DOB": "1993-12-17",
"MaritalStatus": "false",
"CreditCardType": "jcb"
},
{
"id": 17,
"name": "Zulema",
"gender": "Female",
"DOB": "1990-09-27",
"MaritalStatus": "false",
"CreditCardType": "jcb"
},
{
"id": 18,
"name": "Leoline",
"gender": "Female",
"DOB": "1990-02-02",
"MaritalStatus": "false",
"CreditCardType": "visa-electron"
},
{
"id": 19,
"name": "Bayard",
"gender": "Male",
"DOB": "1997-01-11",
"MaritalStatus": "false",
"CreditCardType": "jcb"
},
{
"id": 20,
"name": "Joanne",
"gender": "Female",
"DOB": "1996-02-01",
"MaritalStatus": "false",
"CreditCardType": "maestro"
},
{
"id": 21,
"name": "Marlee",
"gender": "Female",
"DOB": "1994-11-28",
"MaritalStatus": "false",
"CreditCardType": ""
},
{
"id": 22,
"name": "Mitchell",
"gender": "Male",
"DOB": "1993-03-09",
"MaritalStatus": "false",
"CreditCardType": "maestro"
},
{
"id": 23,
"name": "Jefferey",
"gender": "Male",
"DOB": "1999-09-19",
"MaritalStatus": "false",
"CreditCardType": "jcb"
},
{
"id": 24,
"name": "Jolee",
"gender": "Female",
"DOB": "1951-04-14",
"MaritalStatus": "false",
"CreditCardType": "jcb"
},
{
"id": 25,
"name": "Selma",
"gender": "Female",
"DOB": "1958-08-14",
"MaritalStatus": "false",
"CreditCardType": "mastercard"
},
{
"id": 26,
"name": "Pavlov",
"gender": "Male",
"DOB": "1971-12-24",
"MaritalStatus": "true",
"CreditCardType": "jcb"
},
{
"id": 27,
"name": "Willi",
"gender": "Male",
"DOB": "1999-09-29",
"MaritalStatus": "false",
"CreditCardType": "diners-club-enroute"
},
{
"id": 28,
"name": "Vi",
"gender": "Female",
"DOB": "1988-09-25",
"MaritalStatus": "false",
"CreditCardType": "laser"
},
{
"id": 29,
"name": "Teodoro",
"gender": "Male",
"DOB": "1969-03-02",
"MaritalStatus": "false",
"CreditCardType": "jcb"
},
{
"id": 30,
"name": "Loralyn",
"gender": "Female",
"DOB": "1953-11-27",
"MaritalStatus": "false",
"CreditCardType": ""
}
]
var chart = dc.lineChart('#line');
var mycrossfilter = crossfilter(people);
var ageDimension = mycrossfilter.dimension(function(data) {
return [~~((Date.now() - new Date(data.DOB)) / (31557600000))]
});
var ageGroup = ageDimension.group().reduceCount();
chart
.width(800)
.height(300)
.x(d3.scale.linear().domain([15,70]))
.brushOn(false)
.yAxisLabel("Count")
.xAxisLabel("Age")
.dimension(ageDimension)
.group(ageGroup) ;
chart.render();
The working example can be found in below url:
https://jsfiddle.net/ah3qdecr/34/
When I mouseover on the intersection(points of x and y axis), I want the tooltip information to be displayed in label:value format for all properties (eg: Name:Damaris, Gender: Male, Id: 1). Also I would like the color of the tip to be changed (as highlighting) on mouseover.
I've used title(), tooltips, d3 tip but couldn't get the desired output.
Can someone help please.
You are going to add an event handler for your body and the circles inside your svg canvas:
d3.select('body').on('mouseover', function() {
d3.selectAll('circle.dot')
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div.html(d) // Here is the output of the data
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
});
Then you will have to add the tooltip and append it to the body:
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
And last but not least here is an example for the styling of the tooltip:
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: rebecca;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
So now you've got a working tooltip, but your problem at all is the missing data inside the circle. Have you tried to enrich your points with the left data?
A working example based on your fiddle: https://jsfiddle.net/ah3qdecr/58/

Categories