Why does the country with no data always go on top? - javascript

I have a GeoJSON map and I am trying to hook it up in Highmaps. This map consists of 4 small squares ("properties": {"name":"shape1"}) that will have data and 1 big square that will never have data ("properties": {"name":"base"}) The purpose of this big square is to be a background shape for the others.
The problem is that the big shape will always be on top of the small ones. I have tried both of these arrangements in the GeoJSON file:
placing the big shape before the small ones
placing the big shape after the small ones
Please see this example
Is there any way to make the shapes with data stay on top of the ones with no data?

Simply for that base element set null value, like this: http://jsfiddle.net/91ut26vz/1 - note it need to be first element in data array.
// Prepare random data
var data = [
{
"name": "base",
"value": null
},{
"name": "shape1",
"value": 728
},
{
"name": "shape2",
"value": 710
},
{
"name": "shape3",
"value": 963
},
{
"name": "shape4",
"value": 541
}
];

Related

Why does the value of the "parent" get the sum of the values of the "children" and not the value of itself in the TreeMap?

I could not understand why when a "parent" has value, he still does not receive his own value and still receives as the value the sum of the values of "his children".
Although it is recorded in the doc that when a "parent" has a value he does not inherit the values of his children:
Amcharts Doc:https://www.amcharts.com/docs/v4/chart-types/force-directed/
Code:
chart:
let chart = am4core.create("chartdiv",am4charts.TreeMap)
InputJson:
const jsonData =[{
"name": "First",
"value": 2390, //Parent value
"children": [
{ "name": "A1", "value": 0.4 }, //children value
{ "name": "A2", "value": 0.4 }, //children value
{ "name": "A3", "value": 0.1917355900000002 } //children value
]
}, {
"name": "Second",
"value": 5933, //Parent value
"children": [
{ "name": "B1", "value": 0.2332 }, //children value
{ "name": "B2", "value": 0.323 }, //children value
{ "name": "B3", "value": 0.122332 } //children value
]
}]
TreeMap levels:
const level1 = chart.seriesTemplates.create("0");
let level1_column = level1.columns.template;
const level1_bullet = level1.bullets.push(new am4charts.LabelBullet());
level1_bullet.label.text = "{value}"; //The value is the sum of the values of all his children.
const level2 = chart.seriesTemplates.create("1");
let level2_column = level2.columns.template;
const level2_bullet = level2.bullets.push(new am4charts.LabelBullet());
level2_bullet.label.text = "{value}"; //The value is of the child.
Amcharts Doc TreeMap: https://www.amcharts.com/docs/v4/chart-types/treemap/
Console:
I need the parent's value column to be a red value object and not a yellow object.(As in InputJson)
I had similar problem, and I found your question on GitHub as an issue, but I don't like the fact that the only answer I found about this problem, is "this is not possible".
You cannot set the parent value to be a custom number, because it's always calculated from the children values. It's true.
However, you can calculate custom item values for the purpose of displaying your data, and use custom tooltip to show the real values.
Just to give you an example:
In my case, I added the children dynamically on hit event, so initially the parent had its own value, but after inserting children with values that are not related to its parent value, the whole chart was messed up.
Instead of using the real data as item value, I calculated it based on the parent's item value and the children's real values:
For the root element, I used a fix number (e.g. 10000).
For every item that has parent, I calculated it's item value by dividing the parent's item value with the sum of the children's real values, and multiplying it with the item's real value. It gives a value that is proportional to the parent and the other children.
But this method is also useful, when you have items with 0 or very small value, but you want to show them with a fix value. I also found a question about this on github, with the same "this is not possible" answer.
I hope this answer will be helpful for someone.

Reducing redundant information in a JSON object with javascript and combining values

I have a CSV of results that looks at a picture and makes a guess at whether or not a picture contains a certain attribute. In this case if the subject in the picture is male or female.
I'm converting this CSV to JSON with javascript/node and I want to take the attributes and their values and put them in an array inside of one object per pciture. Right now each line of the CSV measures and attribute but it means at least two lines per image.
Simple version of the csv:
path, detect_id, score, x-coord, y-coord, w-coord, h-coord, attribute, value
picture_1.jpg,0,1.44855535,74,54,181,181,genderf,0.024716798
picture_1.jpg,0,1.44855535,74,54,181,181,genderm,0.975283206
I can convert this CSV to JSON and then at least group items together by their path/filename.
But that leaves a lot of redundant information out there and I want to put my Attributes and their Value together in a nested object inside of the main one.
Like:
Path: picture_1.jpg
Attributes: [genderf: 0.025,
genderm: 0.985]
other_info: other info
Right now I'm using lodash to create the objects as you see below but if I try to map through the attributes I end up pushing out every element except the last one.
So I can create the object with the following code.
var result =
_([...arr1, ...arr2])
.concat()
.groupBy("path")
.value();
Where arr1 and arr2 is the data from one line of the output csv. All the information is the same except the attribute and its value.
That gets me this object:
{
"picture_1.jpg": [
{
"path": "picture_1.jpg",
"detect_id,": "0",
"score,": "1.44855535",
"coordinates": [
{
"x,": "74",
"y,": "54",
"w": "181",
"h": "181"
}
],
"attribute": "genderf",
"value": "0.024716798"
},
{
"path": "picture_1.jpg",
"detect_id,": "0",
"score,": "1.44855535",
"coordinates": [
{
"x,": "74",
"y,": "54",
"w": "181",
"h": "181"
}
],
"attribute": "genderm",
"value": "0.975283206"
}
]
}
Which at least groups pictures together based on the path heading but a lot of the information is redundant and this is just measuring one attribute.
You could just iterate all csv-lines and build an object/map while keeping track of already found file-names/paths. If you encounter a line whose path already exists in the map, just append the attribute/value pair. Something like this (note that I've changed the coords delimiter for the sake of simplicity and that it needs proper error handling):
const data = ["picture_1.jpg,0,1.44855535,74;54;181;181,genderf,0.024716798", "picture_1.jpg,0,1.44855535,74;54;181;181,genderm,0.975283206"];
function createImageDataMap(dataArr) {
const imageDataResult = {};
for (const imgData of dataArr) {
const currData = parseImgDataLine(imgData);
if (!imageDataResult[currData.path]) {
imageDataResult[currData.path] = {
attributes: [], other_info: {
score: currData.score,
detectId: currData.detectId,
coords: currData.coords
}
}
}
imageDataResult[currData.path].attributes.push({[currData.attribute]: currData.value});
}
return imageDataResult;
}
function parseImgDataLine(line) {
const attributes = line.split(',');
return {
path: attributes[0],
detectId: attributes[1],
score: attributes[2],
coords: attributes[3],
attribute: attributes[4],
value: attributes[5]
}
}
console.log(JSON.stringify(createImageDataMap(data)));
// prints {"picture_1.jpg":{"attributes":[{"genderf":"0.024716798"},{"genderm":"0.975283206"}],"other_info":{"score":"1.44855535","detectId":"0","coords":"74;54;181;181"}}}

D3 - Update chart based on data keys

I am new to D3 and I would like to train myself on some scatterplot chart (based on the one from the NYT : Student debt.
I managed to recreate a graph like this one : Oklahoma Colleges.
Now, I have much more entries than the Oklahoma chart, so my chart is not very readable and I would like to filter the data based on a button with which I can select to display only the "public" colleges or the "private" ones.
I have read many tutorials about the ENTER-UPDATE-EXIT methods but I still have some trouble in applying it practically on my case.
Assuming the following JSON file :
[ {
"Id": 1,
"Name": "College A",
"Type": "Public" }, {
"Id": 2,
"Name": "College B",
"Type": "Private" }, {
"Id": 3,
"Name": "College C",
"Type": "Public" }, {
"Id": 4,
"Name": "College D",
"Type": "Public" }, {
"Id": 5,
"Name": "College E",
"Type": "Private" }, {
"Id": 6,
"Name": "College F",
"Type": "Private" }, ]
I would like to achieve the following algorithm :
button.on("change"){
If value == "public" :
display data where data.type == "public"
Else
display data where data.type == "private"
}
My first solution was to create a SVG each time I push the button (and erase the previous SVG) with the new dataset. But I think there is a much nicer way to do this :)
Can you help me ?
Thank you !
EDIT : following #sapote warrior answer -
Here what I do when I load the data :
d3.json("data.json", function(data) {
//Coerce string to numbers
...
dataset = data;
...
//Add axis and legend
}
And when I click to one of the two button :
function update(input){
var data = [];
for(i in dataset) {
if(dataset[i]["Type"] == input)
data.push(dataset[i]);
}
test = data; //Global scope variable, to check if new data is here on the console
circles = svg.selectAll(".circle")
.data(data);
circles.exit().remove();
circles.enter().append("circle")
.attr("class","circle")
...
}
But this doesn't work perfectly. Circles appear correctly when first click to any button, then they not all disappear when I click to the second button, and the new data doesn't seem to be correctly appended.
Hum, still have some issue understanding the enter-update-exit process ^^
EDIT : Ok problem solved ! I have just made some mistakes when implementing the enter-update-exit methods. Did it with a reduced dataset to understand the issue and now it's clear in my mind :)
I think I may be able to help you. Assuming that your circles are already displayed on the SVG, one way to do it is build a new array of values when your button is clicked that are of type "Public" or "Private". Something like this:
publicButton.on("click", function() {
newData = [];
for(i in existingDataArray) {
if(existingDataArray[i]["Type"] == "Public")
newData.push(existingDataArray[i]);
}
Now you can use this new data with the .data().enter().exit().remove() methods that you mentioned to append new data to your circle objects. After that you can remove those circles that aren't in the new data, and keep those that are. Those that you keep you can then doing something to them like update their color or nothing at all if you like. Sort of like this:
var circles = svg.selectAll("circle").data(newData);
circles.exit().remove();
circles.enter().attr("fill", ...);
}
Hopefully this helps some, let me know if you have any questions.

Add new attribute to an existing JSON inside FOR loop

I am trying to populate bootstrap-carousel with some more detailed JSON file from database.I am adding JSON details for the sake of detailed understanding. Earlier My JSON file was :
old.json
[
{"screen": [{
"img" : "../static/images/product/34.jpg",
"price": "Rs 100",
"href": "#mobile/1234"
},{
"img": "../static/images/product/34.jpg",
"price": "Rs 101",
"href":"#mobile/1234"
},{
"img":"../static/images/product/34.jpg",
"price": "Rs 102",
"href":"#mobile/1234"
},{
"img":"../static/images/product/34.jpg",
"price": "Rs 103",
"href":"#mobile/1234"
}
]},
{"screen": [{
"img" : "../static/images/product/34.jpg",
"price": "Rs 100",
"href": "#mobile/1234"
},{
"img": "../static/images/product/34.jpg",
"price": "Rs 101",
"href":"#mobile/1234"
},{
"img":"../static/images/product/34.jpg",
"price": "Rs 102",
"href":"#mobile/1234"
},{
"img":"../static/images/product/34.jpg",
"price": "Rs 103",
"href":"#mobile/1234"
}
]}
]
Now, I am trying to populate it with some more detailed JSON file.
new.JSON
[
{
"sku": "d58a2ece-4387-41d0-bacb-c4b7935f8405",
"selectedQtyOptions": [],
"selectedSize": "",
"description": "obviate buffoonery exterminating knave uncertainly engulf radiantly dogmatist squadron overcame refinance mopes pastier microphone awaiting begin extinguish plenty prod antecedent holdout schoolmarms Rush Kurosawa clinic Broadways Brie sunnier drove ermine husk gendarme vizier Mithridates feast goggled phase purchasing savviest prologs emails resets admire kilotons maladjustment burns viscounts puked receive Tibetans classifications kneed filtration thorns supply bigness astigmatic butterier differential sensational modernistic Djakarta splint earplug boomed horticulture perishables chanticleers syndicated scantiest cantankerousness splashier variate gneiss permutations typeset protozoa wrangled lawbreakers rumbling describe acerbity revenged golfs stalwart stockading caricatures pannier unpleasant sitter rescinds hazing Burgess coastlines thieved encouragingly forefinger Walpole achieving began spec diabetes Lichtenstein hickory squanders borne compute required bringing remunerative Oreo Pekingeses visualized sociopaths radicals flowerier Pakistan terse fillets barking causes Casey manpower ram glamourize deserves Steuben privatized waterproofs ridding poisons discredits overlong coquettes lichees proclivity floating thousandth Linwood promenading mushroomed stain strode obtusest transiency buckets vanguards straying castigate fathom Sappho restricting rehabilitation restiveness pattered bluest box lacquer noticeably Douro overdone biennially diodes baroque hesitant cleaving corroborates reminiscing disks abundant seven used peremptory employment matchbook fraternizing marigold Diaz vaporizers uncork Royal quick absurder misanthropic nabob blindfolds contemplatives Poincaré Galapagos Willamette punctilious Concord Othello carpal leanness Viacom snorkelers arcs piggybacking pulverized",
"selectedQty": "1",
"title": "dibble",
"brand": "Brand7",
"images": [
{
"image0": "/media/products/9f9734f60620cb52246e9e995b75a9bb.jpg"
}
],
"sizeQtyPrice": [
{
"discountAttributes": "upraised saline frowzy rails clampdown Geritol answer devoutest pressure silky",
"measureUnit": "ltr",
"discountPercent": 3,
"mrp": 8472,
"qty": 6,
"size": 99
},
{
"discountAttributes": "servers ambitiousness billeted brutalized moonstone clerestory Pole hamlet Shelton testaments",
"measureUnit": "ltr",
"discountPercent": 20,
"mrp": 2477,
"qty": 4,
"size": 19
},
{
"discountAttributes": "reeducated schmaltz gnashes marketplaces spill gazetteer bethinks preheats duel parley",
"measureUnit": "gms",
"discountPercent": 13,
"mrp": 6162,
"qty": 9,
"size": 86
}
],
"id": 1
},
{
"sku": "b8ea355d-7acc-455b-a55c-027b0e5c73cd",
"selectedQtyOptions": [],
"selectedSize": "",
"description": "Krasnodar karats northeasters libertarian aromatherapy badly partings sexpot rectangular Pyrenees yeshivahs gybe hollowness attune reuse Alphard Chilean johns Clydesdale acronym marmots itched proposer lushes hush combinations Latino weeps starches Hinayana firmware gamy society gaggle mast ginseng sordidness spiritualist sacking southern niceties grunting oblation arbor measures hobo measured iPad respites rutting sickened Baylor torturers malingers deferring expurgations tighter tenderfoot upload hosteling Apollonian upscale wraps Suzhou bookworm clarioning Ismail filthiest arborvitae descender accountant rendezvousing Didrikson mesquite sedating warlocks whips filigrees skylarking wallet refill inveighs thatch toffees recognizable Nazca foresails clangor eliminate crapped gourds impinges relinquishing duh drizzliest false uncommitted exhibited inhalation fomented crestfallen Bacall Darwinism Laurel gays peter undiluted showoff groceries sleeting immaturity Barclay whimpered Madeleine typhoons afforesting Theodoric beaching Decker merriness cultures luggage subscriptions Thomas map stun lengths Jackie offshoot Condorcet squirting upholstering amber statures unmanning snuck expatriates Gethsemane mongeese rocket reappearances Mantle marinading grotto twinkled stonewalling intermarried yoga vassal magnums parking convening Senecas sculled crimps undisciplined Montoya matchstick Sarah scissors intellects replay Rover seduce forage land Platonic wafer medicinal wooding Cumberland ravishing plummeting bantam choking rhizome Wei skyrocketed tempting concretely Siberia boxed heliotropes crummy alliteration reappears Budweiser lecher blunts supplications perspiring corrective military scurvy so monitoring tossed thymi saprophyte riverbed",
"selectedQty": "1",
"title": "nark",
"brand": "Brand2",
"images": [
{
"image0": "/media/products/2f08f1c38a7b67956e4f9295b6898f36.jpg"
}
],
"sizeQtyPrice": [
{
"discountAttributes": "towns Emily chafing boozers secrete confidentially primitively hospices disarrange misplaces",
"measureUnit": "gms",
"discountPercent": 8,
"mrp": 9942,
"qty": 8,
"size": 67
},
{
"discountAttributes": "amateurish tribune luxuriates staged severity Mia spices Muenster coercion obscure",
"measureUnit": "ml",
"discountPercent": 18,
"mrp": 3104,
"qty": 8,
"size": 43
},
{
"discountAttributes": "hanger hassling misanthropists scary dimly economists Moslem castaway Elam initiative",
"measureUnit": "gms",
"discountPercent": 17,
"mrp": 6260,
"qty": 6,
"size": 72
}
],
"id": 2
},
{
"sku": "7e46f4b1-a083-4eab-8d41-ac594202bd8f",
"selectedQtyOptions": [],
"selectedSize": "",
"description": "avails leg whisking lamaseries rebuilding syllabifying clammiest pretense redcap bellying healthy spaghetti Velveeta shares refunding yellowed danced Peking Darrin pigging illegibly foreign utterly Shakespearean trammelling reports Moran tab okra yipped motorcyclists sweetheart sickbed Serb disgorging Sawyer the incinerator selects each reheats declaimed equestriennes Rolvaag membrane tinselled propagation sighs engraved spookier splurged neuters impersonator Gloucester condemnatory adumbrate citadels Iaccoca mishandled clamming scurries militancy interviewing seized mestizoes lithe Marrakesh isolationism antimatter gossip humanitarians combated tease battering idlers sunset Quaternary striving pattern Brandon heart upended barbiturate overtakes pendant tripe doomsday pejoratives paltriness share tadpoles warming intern fluorides Arawakan honcho sleepiness incorporates typesetters alphabetizes violinists Flanders publicist informer deathbed getaways Iyar Decca schmoozing Tricia ultrasound debugging trepidation suspenseful scrapping rubies exorcized riffling vasectomy tolled bootblack Lott balking PhD hitched utter reprehends snorkel dodges deck dynamical planting conspicuously mottoes totality bedecking bachelor wooed mummification risks Chase weatherproof pear backboard Lieberman fisherman propositional swig ruminants Deena pastiche snob overshadowing spinet apostasy immigrated weighing Christie upraised accruals amphitheatre southwester bulldogs Caracas Trajan primly snowsuit bottomed Woolworth predate biking drill japans potholders uncommon swagging oversteps appositive razing helixes ninetieths prohibitory careered Costello musketeers orator pothooks dumfound express hopelessly franchisers blames semimonthlies transformers histogram radiator canes photoelectric pelves bruised",
"selectedQty": "1",
"title": "Harare",
"brand": "Brand8",
"images": [
{
"image0": "/media/products/2f08f1c38a7b67956e4f9295b6898f36_btZCYFi.jpg"
}
],
"sizeQtyPrice": [
{
"discountAttributes": "deters pyrite excitement Australian wadi protagonists bumpiest Caxton bundling monotony",
"measureUnit": "ltr",
"discountPercent": 5,
"mrp": 9355,
"qty": 1,
"size": 80
},
{
"discountAttributes": "puppies smudge moderator constellations invasion Asgard goggle compendiums atrophy tents",
"measureUnit": "Kg",
"discountPercent": 7,
"mrp": 4183,
"qty": 2,
"size": 19
},
{
"discountAttributes": "jailer allotting kindness veers Moss invalidation Brahmanism xenophobia warmhearted looping",
"measureUnit": "ml",
"discountPercent": 16,
"mrp": 1956,
"qty": 1,
"size": 33
}
],
"id": 3
},
{
"sku": "d1cd71a8-9dc5-4724-b269-473ede28a1d7",
"selectedQtyOptions": [],
"selectedSize": "",
"description": "foolish interpolates trumpet monographs ferried inboards Forster tike grammatically sunroof vaporizing Sweden demure retouching completely robbing readies unloose guiltless tatty unobservant cuffs fortieth wither rigorously paradoxically snowmobiling charts clenching planning dealing lesions bicameral pertly chaffinches grumpiness private purled insanely attainment proposal Fatima execrates pshaws chars actuators turboprop soughed kicking majors conquistadores Cynthia septuagenarians kneecaps titans attractions larvas invigorating trunking Shevat recluse Trina slenderness kinking falsified logistically hogged skyrocketing ordinal avoiding trademarked underfoot garter sacrificial pricey nosedive bachelors deiced heave dictatorial muffing prayed rewinding recopied limpidly Crichton conversion chitterlings signets Aiken Froissart turnoff snowshoe forded spiralled underwriters flourishes Sade splicer transfusions cesspools lifelike ruckus showering paean voguish Buck copings Russell watchdog magneto pored height zodiac motherland backings Venus obeys scooters nonintervention dinosaur unashamedly anathema hibernate consumerism portended worked mystically existentialist dissatisfies badgers unanimously triplicated Jenny sagacity Windex snoopier nonplusing shovelling Assam putty darn Sulawesi Italians gunnery codify develops rhinos upwards Louise welled experiences socks pinky mewed Camille claimants swirl squattest ware parenthetic bonitoes hydrangeas decolonizing omit skyjacks Gorky financiers province flywheel southeastward Bayeux updated yowl Tulsidas macintosh sprees pralines systolic uncommoner cilium tromping Asimov heinous cordoned combated camerawomen syndrome identified prizefights heavyweight vertically reflector integrity Hebrides sepulchral loner parrot smooths candidness",
"selectedQty": "1",
"title": "viragoes",
"brand": "Brand0",
"images": [
{
"image0": "/media/products/f791a316ced7b3b774bd61e138197224.jpg"
}
],
"sizeQtyPrice": [
{
"discountAttributes": "chinos theosophy misdemeanor irrigates school Pullman sombrely suspect vortex baddest",
"measureUnit": "ltr",
"discountPercent": 4,
"mrp": 3102,
"qty": 7,
"size": 66
},
{
"discountAttributes": "Molotov absurd traces pounces contracts clarions thighbone Hesse parricide constrains",
"measureUnit": "m",
"discountPercent": 16,
"mrp": 2773,
"qty": 7,
"size": 18
},
{
"discountAttributes": "detainment gunnysack vied expropriation unobtrusive collectables embracing poster hexing governess",
"measureUnit": "m",
"discountPercent": 6,
"mrp": 9920,
"qty": 6,
"size": 69
}
],
"id": 9
},
{
"sku": "838660bb-7ab9-4f2a-8be7-9602a5801756",
"selectedQtyOptions": [],
"selectedSize": "",
"description": "agreeing vizier bleariest trig appliquéing copulating commissariats Balzac lunchtimes glittery quacking Leoncavallo heehawing Tampax lizards pegged nanosecond centigrade subplots tumbrils give jawed skits nickel discontinues impinged evangelized Platonist waterlines dams symposiums intercessor cognition heavier softener dromedaries bravos immobilize consciously Clemons patch klutzier Kirkpatrick caddying designs Dulles twelfths undemocratic isolationists infected ma homering soliciting minibus pluralism fraternity catalyzed Scorpio pandemonium waxwing starter infuses rebuttals spirals rerunning interrogatories Manuel whomsoever tenderized conjoint baronesses callower parenthetic plusses extend cockier Fokker dewlap Cowper Swammerdam secs hock relaxations Judas Canadian presidency lo wildness Philippe picture beekeeper lull manuals transnational yaw chloroformed perennials distinctive Nottingham antiquaries underneath parted nervously basemen observatories scrubbed encoder egalitarians winnow caddish Hawaiians brownstones robbing exhaustible antagonist benefactresses Plasticine Peace platypi Guzman stippled shuts peacemakers butterfly Bolton grout McCain Lebanon bounce oleander Balkans endearments snowfall spoonerisms furnaces inequities billowy jutting guffaw beautifully penis newtons snuffboxes j Angelita tinkles literature depicts insouciant scribblers blinker disobediently devotees primordial sixties Kalamazoo shear contest classes cripple edging exactest cheat invocation thrived drunkenness Fuller architectures sprite Lillian constricts tucking chastisements walruses guzzlers rejoinder apprenticeships pillory spendthrift omens spoonful contortions precociously intensely motorway guts cahoot sculptor paralytics reminisce meltdown trusts lady pronghorn scurried Campbell micron flawing foals nigher",
"selectedQty": "1",
"title": "smokier",
"brand": "Brand2",
"images": [
{
"image0": "/media/products/f51a649e72694d23962ee77a97872f0e.jpg"
}
],
"sizeQtyPrice": [
{
"discountAttributes": "Beerbohm earldom Stanley seconding hypertension Sayers miserly epitome retires ditching",
"measureUnit": "m",
"discountPercent": 15,
"mrp": 5065,
"qty": 6,
"size": 83
},
{
"discountAttributes": "confine Newman bagel cornflower rears generator goaded midweeks drain cigarillo",
"measureUnit": "Kg",
"discountPercent": 12,
"mrp": 2284,
"qty": 9,
"size": 13
},
{
"discountAttributes": "eerier fizzes lessened rotisserie developer Gray industrial callused convergences ampoule",
"measureUnit": "gms",
"discountPercent": 4,
"mrp": 6816,
"qty": 8,
"size": 18
}
],
"id": 14
}
]
As you can see, I need to group my new.JSON as a group of 4 under screen attribute. For that I wrote one for loop:
mainApp.controller('MultiCarouselController', function($scope, $http) {
$scope.products = [];
$scope.Math = Math;
$http.get("/get_broad_category_products/?BroadCategory=BroadCategory3")
.success(function (response) {
$scope.products = response;
var iteratation = Math.ceil($scope.products.length/4);
var carouselJson = [];
for(var index = 0; index < iteratation; index++){ // kinda 2D matrix as [0,1],[0,2],[1,1],[1,2]
var temp = [];
for (var i = (index*4) ; i < (4*(index+1)) ; i++){
temp = temp.concat($scope.products[i]) // concatenating 4 JSON as a group
}
carouselJson.push(temp); // pushing group to new JSON
}
console.log(carouselJson);
}).error(function(){
console.log('Error happened ... ');
});
});
This angularJS controller is working completely fine, how can I add "screen" property and then add group of 4 JSONs to it
I though about doing something like:
for(var index = 0; index < iteratation; index++){ // kinda 2D matrix as [0,1],[0,2],[1,1],[1,2]
var temp = [];
for (var i = (index*4) ; i < (4*(index+1)) ; i++){
temp = temp.concat($scope.products[i]) // concatenating 4 JSON as a group
}
var jsTemp = [] ;
carouselJson.push(jsTemp.screen.push(temp)); // Errrrr.... screen property is not there in jsTemp. Now ????
}
Small help might do the trick !!!
I am not at all a fan of angular so do not know that much about how it handles JSON.
Yet JSON is just a serialized object and thus it is easy to mix and match as long as you take a few precautions.
Consider the following two json files. JSON1 is a list of products and each product has an id that is unique to that product. The second JSON JSON2 has amendments to the first JSON that have specific names "extraImages", "newItems", "updates", "newData" that we have to add to the first.
Concatenating them will not do as they are not arrays. nor can you just concat JSON strings, it does not work.
You could write a generic Object join function but that will join the two without any contextual knowledge. How does it know where to put extra images? how does it know that each product can be identified by the ID?
To join the two object we need to have pria knowledge of the data structures and the semantic meaning of each item in both files.
Anyways the two JSON files as string.
var JSON1 = `{
"item1":{
"id":100,
"desc":"a product",
"images":[
"img1.jpg",
"img2.jpg",
]
},
"item2":{
"id":101,
"desc":"another product",
"images":"img11.jpg", // this item has only one image so it just has a string
},
"item5":{
"id":105,
"desc":"a product without images",
},
}`;
var JSON2 = `{
"extraImages":[{
"id":101,
"images":[
"imageA.png",
"imageC.png"
]
}],
"newData":[{
"id":100,
"price":100,
}
],
"update":[{
"id":100,
"desc":"Best buy product",
}
],
"newItems":[{
"item3":{
"id":102,
"desc":"Just on the docks",
"images":[
"Blury11.jpg",
]
},
}
}`
So as strings JSON is kind of useless. To hard to search and find data. So JavaScript has a built in object to handle JSON called funnily enough JSON
The JSON object has two methods JSON.stringify(Obj) and JSON.parse(String)
JSON.stringify takes a basic JS data type and converts it into a
JSON string.
JSON.parse takes a json string, from whatever source and converts
it back into a JS Object, Array...
So first step convert both JSON string to objects.
var items = JSON.parse(JSON1);
var extras = JSON.parse(JSON2);
Now we have two normal JS objects that we can manipulate and join.
Lets do the images. The extra images are an array, with each item having an ID and an array of image names.
// we know the name of the object that has extra images so check if its there
// and then itterate all the items in the array
if(extras.extraImages !== undefined){ // Does this property exist
extras.extraImages.forEach(function(item){ // itterat over each item
var arrayOfImages;
// do the images exist and if so are they as an array
if(item.images !== undefined && typeof item.images === "array"){
arrayOfImages = item.images;
}
// the data structure may vary depending on what is serving the JSON
// data so you can add code to take differing types
// Now to find the matching item in the items object
// check that there is an array of images to add and tha
// the item we have has an item id we can use to find the existing item
if(arrayOfImages !== undefined && item.id !== undefined){
// continue on further down
So we have found an extra images item that has an ID and array of image names. We need to find the product if it exists that has that ID. As we will do that many times lets write a function to do that.
// pass the items object that may contain the item with the ID we are looking for
function getItemById(items,id){
for(var itemName in items){ // iterate each named item. itemName is
// just a variable it could be any var name.
// It contains a string holding each enumerable
// properties name in turn
Now check that the named property has a id you may be tempted to check if the id has the id we are looking for.
if(item[itemName].id === id){
This will throw an error if the item does not have an id and there are many reasons an enumerable property may appear that is not correctly structured. So check id exists then check its value. Unlike C/C++/C# the order of comparisons is always left to right. At the first false the if( will drop out of the () and not do any further comparison.
It is thus safe in javascript to test for the second condition as long as you test first that it will not throw ReferenceError: id is not defined
if(items[itemName].id !== undefined && items[itemName].id == id){
will never throw an error while
if(items[itemName].id == id && items[itemName].id !== undefined ){
can if id does not exist.
Anyways I diverge.
if(items[itemName].id == id && items[itemName].id !== undefined ){
// found the item with matching id
return items[itemName]; // so return it
}
}
return undefined; // nothing found that matches so return undefined
} //end of function
So back to adding extra images. We have just tested and found a extraimage item with an id and some extra image names.
// use the function to get the item
var existingItem = getItemById(items,item.id);
// check that we found one
if(existingItem !== undefined){
// check to see if it has a images
if(existingItem.images === undefined){
// no image so creat images and add an empty array
existingItem.images = []
}else // if it does is it an array
if(typeof existingItem.images !== "array"){
// not an array we will assume what is there
// is an image description of some type
// so convert the existing images object into
// an array and add the existing item into it
existingItem.images = [existingItem.images];
}
// now we are sure the images array is correct so lets
// add the new images to i
existingItem.images existingItem.images.concat( arrayOfImages);
}
}
}); // end of forEach lop
} // endo of adding new images
So wrap it all up
// code to join extraImages to items
if(extras.extraImages !== undefined){
extras.extraImages.forEach(function(item){
var arrayOfImages;
if(item.images !== undefined && typeof item.images === "array"){
arrayOfImages = item.images;
}
if(arrayOfImages !== undefined && item.id !== undefined){
var existingItem = getItemById(items,item.id);
if(existingItem !== undefined){
if(existingItem.images === undefined){
existingItem.images = []
}else
if(typeof existingItem.images !== "array"){
existingItem.images = [existingItem.images];
}
existingItem.images existingItem.images.concat( arrayOfImages);
}
}
});
}
// was going to show all the other joins for extras.update, newItems, and newData
// too much for one answer.
I see this is becoming a long answer. I'll assume that you see what is being done and how that is used to join two objects together while conforming to its semantic meaning. You should be able to write a function to do the same for your data. Convert both JSON strings to object via JSON.parse iterate the object structure obeying the semantic meaning of the data, creating or appending data as needed.
The last thing, as I assume you need the joined data as JSON string, is to convert the updated object back into a json string.
JSON1 = JSON.stringify(items); // convert the updated items object to a JSON string
Now you can pass it on back to Angular's JSON abstraction layer to do what you need.
Hope this helps. And maybe there is a way in Angular but as no one has answered with what is needed and I don't want to sully my purist ways (yucky Angular), this will give you some extra JS grounding and allow you to fix your problem.
If I am reading this correctly, you want a new property to be added to each element inside the temp array. For this you can try creating a new object from your $scope.products[i].
for(var index = 0; index < iteratation; index++){ // kinda 2D matrix as [0,1],[0,2],[1,1],[1,2]
var temp = [];
for (var i = (index*4) ; i < (4*(index+1)) ; i++){
var destObj = $scope.products[i];
destObj.screen = 'xx' // Assign your value here.
temp = temp.concat(destObj) // concatenating 4 JSON as a group
}
carouselJson.push(temp);
}
Hope this helps...
this linked helped me
JavaScript Array Push key value
changed my loop like:
var carouselJson = [];
for(var index = 0; index < iteratation; index++){ // kinda 2D matrix as [0,1],[0,2],[1,1],[1,2]
var temp = [];
var screen = ['screen'];
var obj = {};
for (var i = (index*4) ; i < (4*(index+1)) ; i++){
temp = temp.concat($scope.products[i]); // concatenating 4 JSON as a group
}
obj[screen]=temp;
carouselJson.push(obj); // pushing group to new JSON
}
$scope.mCarousels = carouselJson;

Nested JSON structure to build side-by-side d3.js charts

I'm currently stuck on how to traverse a JSON structure (I created) in order to create side-by-side donut charts. I think I've created a bad structure, but would appreciate any advice.
I'm working from Mike Bostock's example here: http://bl.ocks.org/mbostock/1305337 which uses a .csv file for source data.
In that example he uses d3.nest() to create a nested data structure with an array of flight origins.
var airports = d3.nest()
.key(function(d) { return d.origin; })
.entries(flights);
He is then able to bind that new data structure to a new div selector:
var svg = d3.select("body").selectAll("div")
.data(airports)
.enter().append("div")
Which allows him to create a donut chart for each flight origin.
My JSON data looks like the following:
{"years": [
{
"year": 2015,
"type": "bestSellers",
"chartOne": [
{
"label": "smarties",
"value": 11
},
{
"label": "nerds",
"value": 13
},
{
"label": "dots",
"value": 16
},
{
"label": "sour patch kids",
"value": 61
}
],
"chartTwo": [
{
"label": "Pepsi",
"value": 36
},
{
"label": "sunkist",
"value": 13
},
{
"label": "coke",
"value": 34
}
]}
I'm a CS student, with little experience of data structure best practices and d3.js. The structure I created doesn't look "flat" to me so I'm not sure if I need to use d3.nest(). However, I'm not clear how to traverse chartOne and chartTwo using the structure as is.
I can get to the arrays within the charts:
var chartOne = years[0].chartOne;
var cartTwo = years[0].chartTwo;
But I would like to be able to have one object to access chart1 and chart2. I'm tempted to create another array block in my JSON, but not clear if there isn't a more simple approach.
No, you don't need to use .nest here. The easiest way to build the required data structure is as you suggest (d3 always wants an array to iterate over):
var nestedData = [ years[0].chartOne, years[0].chartTwo ];
After that, it's as simple as cleaning up the accessor functions for your data and Bostock's example works well.
Example here.

Categories