I am using tree layout and I have multiple trees (multiple roots).
How can I get the trees to be packed together and fill the empty space using layout.
Here is an example of my trees:
unpacked trees image
I want them to be more like this:
packed trees image
here is my current layout:
let myDiagram = new go.Diagram("myDiagramDiv",
{
layout: new go.TreeLayout({
treeStyle: go.TreeLayout.StyleLastParents,
arrangement: go.TreeLayout.ArrangementHorizontal,
compaction: go.TreeLayout.CompactionBlock,
// properties for most of the tree:
angle: 90,
layerSpacing: 35,
// properties for the "last parents":
alternateAngle: 90,
alternateLayerSpacing: 35,
alternateAlignment: go.TreeLayout.AlignmentBus,
alternateNodeSpacing: 20,
})
});
#HumanTarget has the right idea. Here's an example:
<script type="module">
import * as go from "../release/go-module.js";
import { ArrangingLayout } from "../extensionsJSM/ArrangingLayout.js";
import { PackedLayout } from "../extensionsJSM/PackedLayout.js";
const $ = go.GraphObject.make;
const myDiagram =
$(go.Diagram, "myDiagramDiv",
{
layout: $(ArrangingLayout,
{
primaryLayout: $(go.TreeLayout, { angle: 90 }),
arrangingLayout: $(PackedLayout, { spacing: 10 }),
})
});
myDiagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape, { fill: "white" },
new go.Binding("fill", "color")),
$(go.TextBlock, { margin: 8 },
new go.Binding("text"))
);
myDiagram.model = new go.GraphLinksModel(
[
{ key: 1, text: "Alpha", color: "lightblue" },
{ key: 2, text: "Beta", color: "orange" },
{ key: 3, text: "Gamma", color: "lightgreen" },
{ key: 4, text: "Delta", color: "pink" },
{ key: 5, text: "Epsilon", color: "lightblue" },
{ key: 6, text: "Zeta", color: "orange" },
{ key: 7, text: "Eta", color: "lightgreen" },
{ key: 8, text: "Theta", color: "pink" },
{ key: 9, text: "Iota", color: "lightblue" },
{ key: 10, text: "Kappa", color: "orange" },
{ key: 11, text: "Lambda", color: "lightgreen" },
{ key: 12, text: "Mu", color: "pink" },
{ key: 13, text: "Nu", color: "lightblue" },
{ key: 14, text: "Xi", color: "orange" },
{ key: 15, text: "Omicron", color: "lightgreen" },
{ key: 16, text: "Pi", color: "pink" },
],
[
{ from: 1, to: 2 },
{ from: 1, to: 3 },
{ from: 4, to: 5 },
{ from: 4, to: 6 },
{ from: 6, to: 7 },
{ from: 8, to: 9 },
{ from: 9, to: 10 },
{ from: 11, to: 12 },
{ from: 13, to: 14 },
{ from: 13, to: 15 },
{ from: 13, to: 16 },
]);
</script>
Result:
But note that PackedLayout will treat each subtree as occupying a rectangular area, so it won't try to fit subtrees together where one or both of the subtrees has some empty space.
I am following Colt Steele's React course. Sadly, the course is outdated so I chose to migrate to the latest versions of libraries myself.
Coming to the point, I am now facing this error where I am not able to extract URL params using the useParams hook in my functional component. I am pasting my code below for the community to check.
App.js
import Palette from './Palette';
import seedPalettes from './assets/seedPalettes'
import './css/App.css'
import { generatePalette } from './assets/colorHelpers';
import { Routes, Route, Link, useParams } from 'react-router-dom';
function App() {
const { id } = useParams()
const findPalette = id => {
return seedPalettes.find(function (palette) {
return palette.id == id;
})
}
console.log(id);
return (
<div className='App'>
<Routes>
<Route path='/' element={<h1>Welcome Home</h1>} />
<Route path='/palette/:id' element={<Palette palette={generatePalette(findPalette(id))} />} />
</Routes>
{/* <Link to='/palette'>See Palette</Link> */}
{/* <Palette palette={generatePalette(seedPalettes[4])} /> */}
</div>
);
}
export default App;
seedPalettes.js
export default [
{
paletteName: "Material UI Colors",
id: "material-ui-colors",
emoji: "🎨",
colors: [
{ name: "red", color: "#F44336" },
{ name: "pink", color: "#E91E63" },
{ name: "purple", color: "#9C27B0" },
{ name: "deeppurple", color: "#673AB7" },
{ name: "indigo", color: "#3F51B5" },
{ name: "blue", color: "#2196F3" },
{ name: "lightblue", color: "#03A9F4" },
{ name: "cyan", color: "#00BCD4" },
{ name: "teal", color: "#009688" },
{ name: "green", color: "#4CAF50" },
{ name: "lightgreen", color: "#8BC34A" },
{ name: "lime", color: "#CDDC39" },
{ name: "yellow", color: "#FFEB3B" },
{ name: "amber", color: "#FFC107" },
{ name: "orange", color: "#FF9800" },
{ name: "deeporange", color: "#FF5722" },
{ name: "brown", color: "#795548" },
{ name: "grey", color: "#9E9E9E" },
{ name: "bluegrey", color: "#607D8B" }
]
},
{
paletteName: "Flat UI Colors v1",
id: "flat-ui-colors-v1",
emoji: "🤙",
colors: [
{ name: "Turquoise", color: "#1abc9c" },
{ name: "Emerald", color: "#2ecc71" },
{ name: "PeterRiver", color: "#3498db" },
{ name: "Amethyst", color: "#9b59b6" },
{ name: "WetAsphalt", color: "#34495e" },
{ name: "GreenSea", color: "#16a085" },
{ name: "Nephritis", color: "#27ae60" },
{ name: "BelizeHole", color: "#2980b9" },
{ name: "Wisteria", color: "#8e44ad" },
{ name: "MidnightBlue", color: "#2c3e50" },
{ name: "SunFlower", color: "#f1c40f" },
{ name: "Carrot", color: "#e67e22" },
{ name: "Alizarin", color: "#e74c3c" },
{ name: "Clouds", color: "#ecf0f1" },
{ name: "Concrete", color: "#95a5a6" },
{ name: "Orange", color: "#f39c12" },
{ name: "Pumpkin", color: "#d35400" },
{ name: "Pomegranate", color: "#c0392b" },
{ name: "Silver", color: "#bdc3c7" },
{ name: "Asbestos", color: "#7f8c8d" }
]
},
{
paletteName: "Flat UI Colors Dutch",
id: "flat-ui-colors-dutch",
emoji: "🇳🇱",
colors: [
{ name: "Sunflower", color: "#FFC312" },
{ name: "Energos", color: "#C4E538" },
{ name: "BlueMartina", color: "#12CBC4" },
{ name: "LavenderRose", color: "#FDA7DF" },
{ name: "BaraRose", color: "#ED4C67" },
{ name: "RadiantYellow", color: "#F79F1F" },
{ name: "AndroidGreen", color: "#A3CB38" },
{ name: "MediterraneanSea", color: "#1289A7" },
{ name: "LavenderTea", color: "#D980FA" },
{ name: "VerryBerry", color: "#B53471" },
{ name: "PuffinsBill", color: "#EE5A24" },
{ name: "PixelatedGrass", color: "#009432" },
{ name: "MerchantMarineBlue", color: "#0652DD" },
{ name: "ForgottenPurple", color: "#9980FA" },
{ name: "HollyHock", color: "#833471" },
{ name: "RedPigment", color: "#EA2027" },
{ name: "TurkishAqua", color: "#006266" },
{ name: "20000LeaguesUnderTheSea", color: "#1B1464" },
{ name: "CircumorbitalRing", color: "#5758BB" },
{ name: "MagentaPurple", color: "#6F1E51" }
]
},
{
paletteName: "Flat UI Colors American",
id: "flat-ui-colors-american",
emoji: "🇺🇸",
colors: [
{ name: "LightGreenishBlue", color: "#55efc4" },
{ name: "FadedPoster", color: "#81ecec" },
{ name: "GreenDarnerTail", color: "#74b9ff" },
{ name: "ShyMoment", color: "#a29bfe" },
{ name: "CityLights", color: "#dfe6e9" },
{ name: "MintLeaf", color: "#00b894" },
{ name: "RobinsEggBlue", color: "#00cec9" },
{ name: "ElectronBlue", color: "#0984e3" },
{ name: "ExodusFruit", color: "#6c5ce7" },
{ name: "SoothingBreeze", color: "#b2bec3" },
{ name: "SourLemon", color: "#ffeaa7" },
{ name: "FirstDate", color: "#fab1a0" },
{ name: "PinkGlamour", color: "#ff7675" },
{ name: "Pico8Pink", color: "#fd79a8" },
{ name: "AmericanRiver", color: "#636e72" },
{ name: "BrightYarrow", color: "#fdcb6e" },
{ name: "OrangeVille", color: "#e17055" },
{ name: "Chi-Gong", color: "#d63031" },
{ name: "PrunusAvium", color: "#e84393" },
{ name: "DraculaOrchid", color: "#2d3436" }
]
},
{
paletteName: "Flat UI Colors Aussie",
id: "flat-ui-colors-aussie",
emoji: "🇦🇺",
colors: [
{ name: "Beekeeper", color: "#f6e58d" },
{ name: "SpicedNectarine", color: "#ffbe76" },
{ name: "PinkGlamour", color: "#ff7979" },
{ name: "JuneBud", color: "#badc58" },
{ name: "CoastalBreeze", color: "#dff9fb" },
{ name: "Turbo", color: "#f9ca24" },
{ name: "QuinceJelly", color: "#f0932b" },
{ name: "CarminePink", color: "#eb4d4b" },
{ name: "PureApple", color: "#6ab04c" },
{ name: "HintOfIcePack", color: "#c7ecee" },
{ name: "MiddleBlue", color: "#7ed6df" },
{ name: "Heliotrope", color: "#e056fd" },
{ name: "ExodusFruit", color: "#686de0" },
{ name: "DeepKoamaru", color: "#30336b" },
{ name: "SoaringEagle", color: "#95afc0" },
{ name: "GreenlandGreen", color: "#22a6b3" },
{ name: "SteelPink", color: "#be2edd" },
{ name: "Blurple", color: "#4834d4" },
{ name: "DeepCove", color: "#130f40" },
{ name: "WizardGrey", color: "#535c68" }
]
},
{
paletteName: "Flat UI Colors British",
id: "flat-ui-colors-british",
emoji: "🇬🇧",
colors: [
{ name: "ProtossPylon", color: "#00a8ff" },
{ name: "Periwinkle", color: "#9c88ff" },
{ name: "Rise-N-Shine", color: "#fbc531" },
{ name: "DownloadProgress", color: "#4cd137" },
{ name: "Seabrook", color: "#487eb0" },
{ name: "VanaDylBlue", color: "#0097e6" },
{ name: "MattPurple", color: "#8c7ae6" },
{ name: "NanohanachaGold", color: "#e1b12c" },
{ name: "SkirretGreen", color: "#44bd32" },
{ name: "Naval", color: "#40739e" },
{ name: "NasturcianFlower", color: "#e84118" },
{ name: "LynxWhite", color: "#f5f6fa" },
{ name: "BlueberrySoda", color: "#7f8fa6" },
{ name: "MazarineBlue", color: "#273c75" },
{ name: "BlueNights", color: "#353b48" },
{ name: "HarleyOrange", color: "#c23616" },
{ name: "HintOfPensive", color: "#dcdde1" },
{ name: "ChainGangGrey", color: "#718093" },
{ name: "PicoVoid", color: "#192a56" },
{ name: "ElectroMagnetic", color: "#2f3640" }
]
},
{
paletteName: "Flat UI Colors Spanish",
id: "flat-ui-colors-spanish",
emoji: "🇪🇸",
colors: [
{ name: "JacksonsPurple", color: "#40407a" },
{ name: "C64Purple", color: "#706fd3" },
{ name: "SwanWhite", color: "#f7f1e3" },
{ name: "SummerSky", color: "#34ace0" },
{ name: "CelestialGreen", color: "#33d9b2" },
{ name: "LuckyPoint", color: "#2c2c54" },
{ name: "Liberty", color: "#474787" },
{ name: "HotStone", color: "#aaa69d" },
{ name: "DevilBlue", color: "#227093" },
{ name: "PalmSpringsSplash", color: "#218c74" },
{ name: "FlourescentRed", color: "#ff5252" },
{ name: "SyntheticPumpkin", color: "#ff793f" },
{ name: "CrocodileTooth", color: "#d1ccc0" },
{ name: "MandarinSorbet", color: "#ffb142" },
{ name: "SpicedButterNut", color: "#ffda79" },
{ name: "EyeOfNewt", color: "#b33939" },
{ name: "ChileanFire", color: "#cd6133" },
{ name: "GreyPorcelain", color: "#84817a" },
{ name: "AlamedaOchre", color: "#cc8e35" },
{ name: "Desert", color: "#ccae62" }
]
},
{
paletteName: "Flat UI Colors Indian",
id: "flat-ui-colors-indian",
emoji: "🇮🇳",
colors: [
{ name: "OrchidOrange", color: "#FEA47F" },
{ name: "SpiroDiscoBall", color: "#25CCF7" },
{ name: "HoneyGlow", color: "#EAB543" },
{ name: "SweetGarden", color: "#55E6C1" },
{ name: "FallingStar", color: "#CAD3C8" },
{ name: "RichGardenia", color: "#F97F51" },
{ name: "ClearChill", color: "#1B9CFC" },
{ name: "WhitePepper", color: "#F8EFBA" },
{ name: "Keppel", color: "#58B19F" },
{ name: "ShipsOfficer", color: "#2C3A47" },
{ name: "FieryFuchsia", color: "#B33771" },
{ name: "BlueBell", color: "#3B3B98" },
{ name: "GeorgiaPeach", color: "#FD7272" },
{ name: "OasisStream", color: "#9AECDB" },
{ name: "BrightUbe", color: "#D6A2E8" },
{ name: "MagentaPurple", color: "#6D214F" },
{ name: "EndingNavyBlue", color: "#182C61" },
{ name: "SasquatchSocks", color: "#FC427B" },
{ name: "PineGlade", color: "#BDC581" },
{ name: "HighlighterLavender", color: "#82589F" }
]
},
{
paletteName: "Flat UI Colors French",
id: "flat-ui-colors-french",
emoji: "🇫🇷",
colors: [
{ name: "FlatFlesh", color: "#fad390" },
{ name: "MelonMelody", color: "#f8c291" },
{ name: "Livid", color: "#6a89cc" },
{ name: "Spray", color: "#82ccdd" },
{ name: "ParadiseGreen", color: "#b8e994" },
{ name: "SquashBlossom", color: "#f6b93b" },
{ name: "MandarinRed", color: "#e55039" },
{ name: "AzraqBlue", color: "#4a69bd" },
{ name: "Dupain", color: "#60a3bc" },
{ name: "AuroraGreen", color: "#78e08f" },
{ name: "IcelandPoppy", color: "#fa983a" },
{ name: "TomatoRed", color: "#eb2f06" },
{ name: "YueGuangBlue", color: "#1e3799" },
{ name: "GoodSamaritan", color: "#3c6382" },
{ name: "Waterfall", color: "#38ada9" },
{ name: "CarrotOrange", color: "#e58e26" },
{ name: "JalapenoRed", color: "#b71540" },
{ name: "DarkSapphire", color: "#0c2461" },
{ name: "ForestBlues", color: "#0a3d62" },
{ name: "ReefEncounter", color: "#079992" }
]
}
];
colorHelpers.js
This is where I am creating my palette from a seed palette.
import chroma from 'chroma-js';
const levels = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900];
const generatePalette = (starterPalette) => {
let newPalette = {
paletteName: starterPalette.paletteName,
id: starterPalette.id,
emoji: starterPalette.emoji,
colors: {}
};
for (let level of levels) {
newPalette.colors[level] = [];
}
for (let color of starterPalette.colors) {
let scale = generateScale(color.color, 10).reverse();
for (let i in scale) {
newPalette.colors[levels[i]].push({
name: `${color.name} ${levels[i]}`,
id: color.name.toLowerCase().replace(/ /g, '-'),
hex: scale[i],
rgb: chroma(scale[i]).css().replace(/,/g, ', '),
rgba: chroma(scale[i]).css().replace('rgb', 'rgba').replace(')', ',1.0)').replace(/,/g, ', ')
})
}
}
return newPalette;
}
const getRange = (hexColor) => {
const end = '#fff';
return [
chroma(hexColor).darken(1.4).hex(),
hexColor,
end
]
}
const generateScale = (hexColor, numOfColors) => {
return chroma.scale(getRange(hexColor)).mode('lab').colors(numOfColors);
}
export { generatePalette };
Please help me, as a beginner, it is very overwhelming :(. Also, sorry for the bulky code blocks.
The useParams hook can only access the route match params of a Route within the context of the Routes component rendering it. App is outside the Routes component that renders a route rendering path='/palette/:id'.
You can create a wrapper component to "sip" the id route match param and do the filtering.
import seedPalettes from './assets/seedPalettes';
const findPalette = id => seedPalettes.find(palette => palette.id == id);
const PaletteWrapper = () => {
const { id } = useParams();
const palette = generatePalette(findPalette(id))
return <Palette palette={palette} />;
};
...
function App() {
return (
<div className='App'>
<Routes>
<Route path='/' element={<h1>Welcome Home</h1>} />
<Route path='/palette/:id' element={<PaletteWrapper />} />
</Routes>
</div>
);
}
I have a packed bubble chart that works great. I would like to add a title to each of the larger, separated bubbles. The title should always show and I would like it to be the name of the series. I'm using a split series.
The 'name' attribute shows up in the tooltip, but I would like it to always be displayed.
Here is the code to create the bubbles:
Highcharts.chart('bubble-split-chart', {
chart: {
type: 'packedbubble',
animation: false,
backgroundColor: {
linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 },
stops: [
[0, '#15191b'],
[1, '#15191b']
]
},
},
// remove hamburger button
exporting: {
enabled: false
},
// remove chart watermark (highcharts.com)
credits: {
enabled: false
},
title: {
text: '',
enabled: false
},
tooltip: {
useHTML: true,
pointFormat: '<b>{point.name}</b>'
},
plotOptions: {
packedbubble: {
minSize: '1%',
maxSize: '100%',
zMin: 1,
zMax: 400,
layoutAlgorithm: {
enableSimulation: false,
gravitationalConstant: 0.05,
splitSeries: true,
seriesInteraction: false,
dragBetweenSeries: false,
parentNodeLimit: true
}
},
legend: {
enabled: false
}
},
series: [{
name: 'Test',
data: [{
name: "Lorem",
value: 29.4,
color: 'red'
},
{
name: "Ipsum",
value: 34.1,
color: 'blue'
},
{
name: "Dolor",
value: 7.1,
color: 'green'
}],
}, {
name: 'Test 2',
data: [{
name: 'Lorem',
value: 300.1,
color: 'red'
},
{
name: 'Ipsum',
value: 20.7,
color: 'blue'
},
{
name: "Dolor",
value: 97.2,
color: 'green'
}],
}, {
name: 'Test 3',
data: [{
name: "Lorem",
value: 8.2,
color: 'red'
},
{
name: "Ipsum",
value: 9.2,
color: 'blue'
},
{
name: "Dolor",
value: 13.1,
color: 'green'
}],
}]
});
Is this possible? Also, if this is possible, how can I remove the name from the tooltip?
You can add the labels by using annotations or Highcharts.SVGRenderer class.
To remove the series name from tooltip set:
tooltip: {
headerFormat: '',
...
}
Live demo: http://jsfiddle.net/BlackLabel/6m4e8x0y/4771/
API Reference:
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer
https://api.highcharts.com/highcharts/annotations
https://api.highcharts.com/highcharts/tooltip.headerFormat
First: Thanks for reading, but there is a lot in this, it may be easier to see it in the CodePen examples that are linked at the bottom.
I recently asked a question about how to dynamically create an array for a treemap, and was pointed in the right direction. I have been able to do some simple manipulation to the hash table, but can't figure out how to do the final step.
Currently the treemap has 2 "levels", that was done like this:
var data=[{color:"blue",party:"Democratic",text:"California",value:55},{color:"blue",party:"Democratic",text:"Oregon",value:7},{color:"red",party:"Republican",text:"Texas",value:38},{color:"red",party:"Republican",text:"Georgia",value:16},{color:"grey",party:"Democratic",text:"Arizona",value:11}];
var result = data.reduce(function(hash) {
return function(prev, curr) {
if (hash[curr.color]) {
hash[curr.color].children.push({
text: curr.text,
value: curr.value,
style: {
backgroundColor: curr.color
}
});
} else {
hash[curr.color] = {};
hash[curr.color].children = hash[curr.color].children || [];
prev.push({
text: curr.party,
style: {
backgroundColor: curr.color
},
children: hash[curr.color].children
});
hash[curr.color].children.push({
text: curr.text,
value: curr.value,
style: {
backgroundColor: curr.color
}
});
}
return prev;
};
}(Object.create(null)), []);
Now, what I'm trying to do is bring an additional criteria and add another level. For example, under "Republican" and "Democratic" you'd have subcategories for "Likely", "Leaning", and "Tipping" but for "Toss Up" you wouldn't have any of those.
Here is the end result that I'm trying to make:
series: [{
text: "Democratic",
style: { "backgroundColor": "blue" },
children: [{
text: "Likely",
style: { "backgroundColor": "darkblue" },
children: [{
text: "Alabama",
value: 8,
style: { "backgroundColor": "darkblue" },
}, {
text: "New Mexico",
value: 14,
style: { "backgroundColor": "darkblue" },
}]
}, {
text: "Leaning",
style: { "backgroundColor": "blue" },
children: [{
text: "Florida",
value: 9,
style: { "backgroundColor": "blue" },
}, {
text: "North Carolina",
value: 6,
style: { "backgroundColor": "blue" },
}]
}, {
text: "Tipping",
style: { "backgroundColor": "lightblue" },
children: [{
text: "Utah",
value: 4,
style: { "backgroundColor": "lightblue" },
}, {
text: "Idaho",
value: 5,
style: { "backgroundColor": "lightblue" },
}]
}]
},
{ text: "Republican",
style: { "backgroundColor": "red" },
children: [{
text: "Likely",
style: { "backgroundColor": "darkred" },
children: [{
text: "alabama",
value: 13,
style: { "backgroundColor": "darkred" },
}, {
text: "New Mexico",
value: 14,
style: { "backgroundColor": "darkred" },
}]
}, {
text: "Leaning",
style: { "backgroundColor": "red" },
children: [{
text: "Florida",
value: 9,
style: { "backgroundColor": "red" },
}, {
text: "North Carolina",
value: 6,
style: { "backgroundColor": "red" },
}]
}, {
text: "Tipping",
style: { "backgroundColor": "lightred" },
children: [{
text: "Utah",
value: 27,
style: { "backgroundColor": "lightred" },
}, {
text: "Idaho",
value: 12,
style: { "backgroundColor": "lightred" },
}]
}]
}, {
text: "Toss Up",
style: { "backgroundColor": "grey" },
children: [{
text: "alabama",
value: 10,
style: { "backgroundColor": "grey" },
}, {
text: "New Mexico",
value: 14,
style: { "backgroundColor": "grey" },
}]
},
]
};
I have been trying to figure out how to modify the example I was given to do that, but have been failing for hours. I'm not sure what I should be looking up. I think in the Else statement inside the "prev.push" (line 2040 here) is where the adjustment should be happening, but I don't know how to implement it, I also suspect I need to change the whole approach.
var result = data.reduce(function(hash) {
return function(prev, curr) {
if (hash[curr.party]) {
console.log("if: " + curr.party + " " + curr.category);
hash[curr.party].children.push({
text: curr.text,
value: curr.value,
style: {
backgroundColor: curr.color
}
});
}
else {
console.log("else: " + curr.party + " " + curr.category);
hash[curr.party] = {};
hash[curr.party].children = hash[curr.party].children || [];
hash[curr.party].children.push({
text: curr.text,
value: curr.value,
style: {
backgroundColor: curr.color
}
});
prev.push({
text: curr.party,
style: {
backgroundColor: curr.color
},
children: hash[curr.party].children // children: [{ text: curr.category, children: [{ }] }]
});
hash[curr.category] = {};
hash[curr.category].children = hash[curr.category].children || [];
console.log("category");
prev.push({
text: curr.category,
style: {
backgroundColor: curr.color
},
children: hash[curr.category].children
});
}
return prev;
};
}(Object.create(null)), []);
To wrap up:
Here is a CodePen of the basic structure of the goal
Here is my current code
Earlier the classification was being done based on color, seeing your data I guess we can do it based on party now. As there is another level added to the tree, we can classify that based on category.
So there are many changes - see demo below:
var data = [{"text":"California","value":55,"color":"#000066","party":"Democratic","compare":1,"category":"Likely"},{"text":"Connecticut","value":7,"color":"#000066","party":"Democratic","compare":1,"category":"Likely"},{"text":"Colorado","value":9,"color":"#3333CC","party":"Democratic","compare":2,"category":"Leaning"},{"text":"Florida","value":29,"color":"#9999FF","party":"Democratic","compare":3,"category":"Tipping"},{"text":"Iowa","value":6,"color":"red","party":"Republican","compare":4,"category":"Likely"},{"text":"Alabama","value":9,"color":"#CC3333","party":"Republican","compare":5,"category":"Leaning"},{"text":"Alaska","value":3,"color":"#FF9999","party":"Republican","compare":6,"category":"Tipping"},{"text":"Arizona","value":11,"color":"#666666","party":"Toss-Up","compare":7,"category":"Toss Up"},{"text":"Texas","value":11,"color":"#666666","party":"Toss-Up","compare":7,"category":"Toss Up"}];
var result = data.reduce(function(hash) {
return function(prev, curr) {
if (!hash[curr.party]) {
hash[curr.party] = {};
hash[curr.party].children = hash[curr.party].children || [];
prev.push({
text: curr.party,
style: {
backgroundColor: curr.color
},
children: hash[curr.party].children
});
} else if (hash[curr.party] && hash[curr.party][curr.category]) {
hash[curr.party][curr.category].children.push({
text: curr.text,
value: curr.value,
style: {
backgroundColor: curr.color
}
});
}
if (hash[curr.party] && !hash[curr.party][curr.category]) {
if (curr.category == "Toss Up") {
hash[curr.party].children.push({
text: curr.text,
value: curr.value,
style: {
backgroundColor: curr.color
}
});
} else {
hash[curr.party][curr.category] = {};
hash[curr.party][curr.category].children = hash[curr.party][curr.category].children || [];
hash[curr.party].children.push({
text: curr.category,
style: {
backgroundColor: curr.color
},
children: hash[curr.party][curr.category].children
});
hash[curr.party][curr.category].children.push({
text: curr.text,
value: curr.value,
style: {
backgroundColor: curr.color
}
});
}
}
return prev;
};
}(Object.create(null)), []);
console.log(result);
.as-console-wrapper {top: 0;max-height: 100%!important;}