I've a flat file which is of format
"id":1,"depends_on":2
"id":1,"depends_on":4
"id":1,"depends_on":5
"id":2,"depends_on":3
"id":4,"depends_on":5
Normally if I don't have
"id":1,"depends_on":5
I can plot the D3 Layout as follows
When I include "id":1,"depends_on":5
Graph that's being plot will be
Ideally I should have a line between 1 & 5 too, along with other mappings.
1)How can I achieve this?
2)How should the data-structure should be?
Does it really need to have duplicate entries (objects) in various parts of main data-structure ( to obtain in the format D3 needed (parent,children[])
Using d3.layout.force produces
Check out this example, which uses d3.layout.force().
A force layout's data structure involves 2 arrays:
an array of nodes
[{id: 1}, {id: 2}, {id: 3}, {id: 4}]`
and array of links
[
{ source: {id: 1}, target: {id: 2} },
{ source: {id: 1}, target: {id: 3} },
{ source: {id: 2}, target: {id: 4} }
]
The objects used in the nodes array and links array should be the same objects. I.e, in the example above, nodes[0] == links.source[0] should be true.
Related
the dataset is a json file like this
[{from: x, to: y}, {from: x, to: z}] and so on.
partitioned_data = d3.partition().size([2*Math.PI, 100]);
root_node = d3.hierarchy(data).sum(d => d.size);
partitioned_data(root_node);
this is what I have so far
I'm getting this as the root node:
... and root_node.children is still undefined. I'm using an example dataset which is just 99->77, 77->112 and 112->82. I want it to give a hierarchy of root_node = 99 and root_node.children[0] = 77 and so on.
There is a reason why you cannot convert your email data into an hierarchical one:
Your data represents a linked non-hierarchical graph, where every node can be linked to everyone else.
The d3.hierarchy requires data, where each node can have only one parent and no loops allowed. If you identify the parent by fromId, the child by toId, and your data looks like this:
[
{fromId: 1, toId: 2},
{fromId: 2, toId: 3},
{fromId: 3, toId: 1},
]
... you have a link loop and cannot create an hierarchy from that data.
I.e. the following string 'violation buffer' has the following places it needs to apply coloring in html.
[
{ offsetFromStart : 3, length : 3},
{ offsetFromStart : 2, length : 6},
{ offsetFromStart : 4, length : 7},
{ offsetFromStart : 13, length : 3},
]
so the desired effect is
v<span style="background-color:green">i<span style="background-color:red;">ola</span>tion bu</span>f<span style="background-color:blue">fe</span>r
What is the best approach in JS to achieve such effect?
I though about using some binary trees and then concatenate into single string but not sure how to do it.
I'm trying to create a generic To Do list that has tasks and subtasks. Any given To Do list will have one or more tasks, and each task will have one or more subtasks. For each subtask, I'm displaying card that presents the task and subtask, as well as some other relevant information about the user. Thus, the number of cards presented for any given list equals the number of subtasks, and can be categorized by task.
The tricky part for me is that I need to be able to reference these cards (as I will be making an API call to get task and subtask data -- both of which are arrays, incidentally -- from different types of lists), and I'm not sure the best way to reference something that effectively has 2 indexes (task and subtask).
My thinking has been focused on creating a toDoList array of task:subtask objects [{task 1, subtask 1}, {task 1, subtask 2}, {task 2, subtask 1), etc}] -- but when I start doing that I'm getting stuck in two places:
in programmatically creating the key-value pairs (I'm using a nest loop to iterate through tasks and subtasks)
how to reference them later, as I need to associate these task:subtask pairs with specific DOM objects to do perform functions like hiding them, for example.
I have some code but it feels really far off the mark so not even including here. Basically, I feel like there's a simple solution of less than a dozen lines of code that a better programmer than I will see immediately, and I'd appreciate the help. Many thanks!
Not sure how much control you have over writing the data structure, but maybe something like this would work.
The idea here is that you give all subtasks an ID, then keep track of a task's subtasks through an array of subtask IDs.
var tasks = [
{name: 'clean apartment', subtasks: [1, 2, 3]},
{name: 'do the dishes', subtasks: [6]},
{name: 'eat lunch', subtasks: [4, 5]}
];
var subtasks = [
{name: 'vaccuum', id: 1},
{name: 'dust', id: 2},
{name: 'wipe down', id: 3},
{name: 'make sandwich', id: 4},
{name: 'drink a beer', id: 5},
{name: 'soak pans', id: 6},
];
var i, j, l = tasks.length;
for(i; i < l; i++) {
var task = tasks[i],
ll = task.subtasks.length;
for(j=0; j < ll; j++) {
// Now you know the parent task and all its subtasks
}
}
Additionally, if you didn't mind using the help of a library like underscore, you could do it the opposite way. This way you give all tasks an ID, then give subtasks a task field, which maps them to a task. Using underscore's findWhere you can easily lookup the task when iterating over every subtask.
var tasks = [
{name: 'clean apartment', id: 1},
{name: 'do the dishes', id: 2},
{name: 'eat lunch', id: 3}
];
var subtasks = [
{name: 'vaccuum', task: 1},
{name: 'dust', task: 1},
{name: 'wipe down', task: 1},
{name: 'make sandwich', task: 3},
{name: 'drink a beer', task: 2},
{name: 'soak pans', task: 2},
];
for(var i = 0; i < subtasks.length; i++) {
var subtask = subtasks[i],
task = _.findWhere(tasks, {id: subtask.task})
// Now you know the subtask and its task
}
From the comments on my post, I also created a fiddle to give an example of creating subtask cards: http://jsfiddle.net/grammar/ynw0eb25/
Could a structure like this be Ok for the job?
[
{taskId: '1',
subtasks:[{subtaskId:'1', otherAttributes:'...'},
{subtaskId:'2', otherAttributes:'...'},
...
]
},
{taskId: '2',
subtasks:[{subtaskId:'1', otherAttributes:'...'},
...
]
}
....
]
Defining nodes in vis.js, http://visjs.org/network_examples.html , looks like this:
var nodes = [
{id: 1, label: 'Node1'},
{id: 2, label: 'Node2'},
{id: 3, label: 'Node3'},
{id: 4, label: 'Node4'}
];
What I'm trying to find out is, can you create a node double-click (or other event/click type) action, something like so:
var nodes = [
{id: 1, label: 'Node1', double-click: 'Arbitrary_OnClick_Function()'},
{id: 2, label: 'Node2', double-click: 'document.getElementById("div1").innerHTML="Node 2 was clicked"'},
{id: 3, label: 'Node3', double-click: 'https://www.google.com;target="_blank"'},
{id: 4, label: 'Node4', double-click: '#SomePageSection'}
];
Perhaps there's a way to do this combining with angular.js (github.com/edgaraafelix/angular-visgraph) or non-simply through vis.js method on(event,callback) (http//visjs.org/docs/network.html#Methods and http://visjs.org/docs/network.html#Events).
So from that same doc that you have the nodes example from, you eventually create a network e.g.
var network = new vis.Network(container, data, options);
(the data object contains the nodes and edges)
then you can put an event listener on the network, and you know which node you clicked on from the properties like this
network.on( 'click', function(properties) {
alert('clicked node ' + properties.nodes);
});
I had exactly the same need. Starting with Simon's answer I ended up with adding the following code:
network.on("doubleClick", function (params) {
params.event = "[original event]";
window.open("/myurl/?id="params.nodes[0],'_blank');
});
params.nodes[0] is the id of the node I'm using in url.
More examples available in source of this visjs page.
Issues: I this works on any network object you double click. I don't know how to make it work on nodes only...
So I have a scope that has a large chunk of key value pairs, so that I can work with it and make it do a bunch of stuff before I send it.
The problem I am having is I want to change that scope into just a small array of the keys of id with inside of it before I send it
so I have the scope which has the obect that is like this :
$scope.myScope = {name: name 1, id: 1, order: 1}, {name: name 2, id: 2, order: 2}
And I want to turn it into
$scope.FilteredScope = {1,2};
of just the id's. I'm wondering if you can filter this scope inside of the controller before send? I've only ever used filters in stuff like repeats. so inside of the controller, it would filter out the ids and place them in maybe a new scope for sending just the ids. Is this possible?
Thanks!
You could just use array.map (may need to polyfill for older browsers):
angular.module('MyModule', [])
.controller('MyController', function( $scope ) {
$scope.myScope = [
{name: 'name1', id: 1, order: 1},
{name: 'name2', id: 2, order: 2}
];
$scope.ids = $scope.myScope.map( function(obj){
return obj.id;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='MyModule' ng-controller='MyController'>
ids: {{ids | json}}
</div>
Firstly for the $scope.myScope to be a correct Javascript Object ( in this case it is an array of map Objects ), it should be of the form:
$scope.myScope = [{name: "name 1", id: 1, order: 1}, {name: "name 2", id: 2, order: 2}]
Secondly, if assume you want your $scope.filteredScope to be an array of all the id values from the $scope.myScope object.
So it can easily be done like this
$scope.filteredScope = []
for(entry of $scope.myScope) $scope.filteredScope.push(entry.id)
This will lead to an output array like [1,2] which you can then send it.
Please let me know if my assumptions were right.If not please edit your question with more info and I will be happy to help