0

For each node, i have a circle which I color with the help of a function ColorType(d):

 node.append("circle")
     .attr("r", 20)
     .attr("y", -25)
     .style("fill", function(d) { return ColorType(d); })
     .style("stroke-width",0.5)
     .style("stroke",'black')
     .attr("opacity", "1");

My ColorType function is

function ColorType(d){
    for (var i = 0; i < TypesTab.length; i++) {
        if (d.type == TypesTab[i].type) { return ColorAction;}
    }   
}

in the above function, d.type is the type of my node (see below the json file strucutre). And TypesTab[i].type is each of my types stored separately in types, checking if the node type is the same as one of the value of the type in types, if so then applies the ColorAction which colors the node circle.

and here is the ColorAction code, which is embedded in each color picker container that is appended to each type in types, the list which is inserted to #filterColor html dom. so each type has a color picker container which is supposed to color its own type only.

$(document).ready(function () {
    $.getJSON("databeta.json", function (obj) {
        $('#filterColor').data('types', obj.types.map(function (o) {
            // console.log(o.type);
            return o.type;
        })).append(obj.types.map(function (o) {
            return '<li>' + o.type + '<input class="color-picker" type="text"/></li>';
        }).join(''));

        var data = $('#filterColor').data('types'); //stores all types

        mynodes = obj.nodes;
        console.log("mynodes : ", mynodes); //array of all my nodes
        console.log("mynodes : ", mynodes[3].type); //reading the type of the fourth object in the nodes array

        $("#filterColor .color-picker").each(function(){
            $(this).spectrum({
                color: (function (m, s, c) {
                    return (c ? arguments.callee(m, s, c - 1) : '#') +
                        s[m.floor(m.random() * s.length)]
                })(Math, '0123456789ABCDEF', 5), //generate random initial color for each container
                preferredFormat: "rgb",
                showInput: true,
                showPalette: true,
                showAlpha: true,
                palette: [["red", "rgba(0, 255, 0, .5)", "rgb(0, 0, 255)"]],
                change: function(color) {
                    MyNode = d3.select("#node").selectAll(".entreprise").select("circle");
                    MyNode.style("fill", function(d) {
                        return d3.rgb(color.toHexString())
                    });
                    Coloration = d3.rgb(color.toHexString());
                }
            });
        });

    });
});

the problem is that when i hardcode the type in the ColorType(d) function,

if (d.type == "school") { return ColorAction;}

it successfully colors the school typed nodes only. However, if i want to make it dynamic so that it colors the nodes with the type that the color picker is assigned to, it fails, because I can't make the connection with the each of o.type. So the question is to pass the each of o.type into the ColorAction and/or ColorType(d) so that each container only colors the nodes of its own type.

Here is an unsuccessfull attempt, because it doesn't take into consideration the o.type and reads the type in types from a global variable (TypesTab) that holds all types in types:

function ColorType(d){
    for (var i = 0; i < TypesTab.length; i++) {
        if (d.type == TypesTab[i].type) { return ColorAction;}
    }

}

The below is the json structure:

{
    "nodes": [
        {
        "type": "school",
        "country": "US",
        "name": "saint peter's",
        "id": 1006
        },
        {
        "type": "univeristy",
        "country": "Brazil",
        "name": "saint joseph's",
        "id": 1007
        }        
        ...
    ],
    "links": [
            {
            "source": 1006,
            "target": 1007,
            "value": 20            
        },
       ...

    ],
    "types": [
                {
                    "type": "school",
                    "image": "image01"
                },
                {
                    "type": "univeristy",
                    "image": "image02"
                },
                {
                    "type": "company",
                    "image": "image03"
                },
                ...
            ]   
}
jacky
  • 524
  • 1
  • 5
  • 15
  • Its probably not the answer but in general you should use === instead of == in comparisons. If == has not hurt you yet it definitely will. Why - because === tests for both equal value and equal type. See this SO post for an explanation. http://stackoverflow.com/questions/359494/which-equals-operator-vs-should-be-used-in-javascript-comparisons – Vanquished Wombat Nov 15 '16 at 11:56
  • 2
    You have posted a lot of information which can be useful but in this case it masks the issue. Can you break the issue down to a pithy example? – Vanquished Wombat Nov 15 '16 at 11:59
  • OK so you're JSON is incorrectly formatted you have an extra ***comma ,*** after ` { "type": "company", "image": "image03" },` JSON standard does not allow trailing comma – Stephen Ó Connor Nov 15 '16 at 12:25
  • And JSON at line 15 ***...*** ',' or ']' expected, got '.' – Stephen Ó Connor Nov 15 '16 at 12:32
  • Also why are you using $.getJSON why not use d3's built-in function d3.json() to import the data? In fact you are using a lot of jQuery where you might be better to use just d3.js functions? – Stephen Ó Connor Nov 15 '16 at 12:41
  • @theWhiteFox actually the training commas are my fault when trying to build my example to post here, in the real file there is no such thing, it is a valid json file. can you suggest a way to read the json file using the d3 lib? – jacky Nov 15 '16 at 14:22

1 Answers1

2

This how I would read / import JSON. Inside the for in is basic, so you would need to change that part to suit your needs.

d3.json("data.json", function (error, data) { console.log(d3.values(data)); // do this as a check for (var d in data) { d.nodes = +d.nodes; d.links = +d.links; d.types = +d.types; } // svg can go here })

  • i get `TypeError: data.forEach is not a function` – jacky Nov 15 '16 at 16:05
  • @jacky OK so my mistake try a for in instead of a forEach loop. Also this is a great [free d3.js charts book](https://leanpub.com/D3-Tips-and-Tricks) – Stephen Ó Connor Nov 15 '16 at 17:27
  • there is an error again, anyway this is not the answer that directly solves th question. would you provide a working answer to the question – jacky Nov 16 '16 at 07:23