My goal here is to have the childless nodes contain hyperlinks. This is the D3 plugin I'm basing things off of: https://github.com/deltoss/d3-mitch-tree
Image Example
I'm newer to JS and JSON so I'm having difficulties on figuring out how to proceed, especially since there's little to refer to in regard to hyperlinks & JSON. If there's a better way to go about this, I'm certainly open to new ideas.
Thank you in advance
<script src="https://cdn.jsdelivr.net/gh/deltoss/d3-mitch-tree#1.0.2/dist/js/d3-mitch-tree.min.js"></script>
<script>
var data = {
"id": 1,
"name": "Animals",
"type": "Root",
"description": "A living that feeds on organic matter",
"children": [
{
"id": 6,
"name": "Herbivores",
"type": "Type",
"description": "Diet consists solely of plant matter",
"children": [
{
"id": 7,
"name": "Angus Cattle",
"type": "Organism",
"description": "Scottish breed of black cattle",
"children": []
},
{
"id": 8,
"name": "Barb Horse",
"type": "Organism",
"description": "A breed of Northern African horses with high stamina and hardiness. Their generally hot temperament makes it harder to tame.",
"children": []
}
]
}
]
};
var treePlugin = new d3.mitchTree.boxedTree()
.setData(data)
.setElement(document.getElementById("visualisation"))
.setMinScale(0.5)
.setAllowZoom(false)
.setIdAccessor(function(data) {
return data.id;
})
.setChildrenAccessor(function(data) {
return data.children;
})
.setBodyDisplayTextAccessor(function(data) {
return data.description;
})
.setTitleDisplayTextAccessor(function(data) {
return data.name;
})
.initialize();
</script>
Chain this method before .initialize():
.on("nodeClick", function(event, index, arr) {
if (!event.data.children.length) {
console.log('you clicked a child-less item', event.data);
}
})
Inside the condition, event.data is the clicked childless item. Feel free to place URLs inside those objects and use those URLs to navigate away.
Taken from the repo's /examples folder, where I found one named Advanced example with Node Click Event.
According to the comment on the same page, you can also achieve this using the options syntax:
/* const tree = [
place your data here...
]; // */
new d3.mitchTree.boxedTree({
events: {
nodeClick({ data }) {
if (!data.children.length) {
console.log('You clicked a childless item', data);
}
}
}
})
.setData(tree)
// ...rest of chain
.initialize();
Related
Hi I'm currently creating an application to gather data form a website, and as I've researched you can used Json for that, now I have created a script to gather data, at first i have no problem with it, but when I cam across with a multi tree json i started having trouble.
here is my Json
{
"orders": [
{
"line_items": [
{
"id": 7660469767,
"name": "Personalised design - purple",
"properties": [
{
"name": "personalised text 1",
"value": "2"
},
{
"name": "personalised text 2",
"value": "Nuri &"
},
{
"name": "personalised text 3",
"value": "Samira"
}
],
}
]
}
]
}
I need to get the order.line_items.properties.value.
I tried this code but it says it does not work.
$.getJSON(order.json, function (data) {
$.each(data.orders.line_items.properties, function (index, value) {
$.each(this.value, function () {
console.log(this.text);
});
});
});
Can someone help me?
$.each(data.orders[0].line_items[0].properties, function (index, value) {
console.log(value.value);
});
Both orders and line_items are array, so it should have an access to array index first before accessing other object. And you don't have to use extra each in your code. The value above is an object for each properties. You can retrieve value there.
I'm completely rebuilding my website (originally hacked together with Wordpress) using Laravel and AngularJS. It's been a massive learning experience and I think I'm nearly there but for one problem.
On my site 'schemes' (or courses) are made up of 'units' which are made up of 'lessons'. Retrieving this data is fine, using Eloquent I retrieve valid JSON like this made up example...
[
{
"id": "1", //Scheme Id
"title": "Sports",
"description": "This is a Sports course!",
"units": [
{
"id": "1",
"title": "Tennis",
"lessons": [
{
"id": "6",
"title": "Serving"
},
{
"id": "7",
"title": "Hitting the ball with top-spin"
}
]
},
{
"id": "2",
"title": "Athletics",
"lessons": [
{
"id": "1",
"title": "Long Jump"
},
{
"id": "2",
"title": "Hurdling Technique"
}
]
},
{
"id": "4",
"title": "Golf",
"lessons": [
{
"id": "4",
"title": "Pitching"
},
{
"id": "5",
"title": "Putting"
}
]
}
]
}
....
]
Separately I have a simple array of completed lesson ids for a particular user like this...
[2, 6, 8, 9] ///User has completed lessons with ids of 2,6,8 and 9
In my view I'm using nested ng-repeat loops like so...
...
<div ng-controller="SchemesController">
<div ng-repeat="scheme in schemes">
<h1>{{scheme.title}}</h1>
<div ng-repeat="unit in scheme.units">
<h3>{{unit.title}}</h3>
<div ng-repeat="lesson in unit.lessons">
<div>{{lesson.title}}: {{status}}</div>
</div>
</div>
</div>
</div><!--[end of ng-controller="SchemesController"]-->
....
SchemesController (v simple!) looks like this...
var app = angular.module('schemesApp', []);
app.controller('SchemesController', function($scope){
$scope.schemes=jsonData;
});
The problem is I have no idea how to populate the {{status}} field which I want to state simply 'Complete' or 'Incomplete. I investigated whether I could somehow add this info to my original array like this...
"lessons": [
{
"id": "6",
"title": "Serving",
"status": "Complete" //populated somehow
},
{
"id": "7",
"title": "Hitting the ball with top-spin",
}
]
but I got nowhere slowly. Is there a way to do this (I've played around with underscore.js and felt this could help?).
Or do I populate {{status}} from creating and calling a javascript function?!?
ANY help that anyone could offer would be incredible. I'm a school teacher and for some sadistic reason I find a bit of programming/web design a fun use of my spare time so I apologise if this is a stupid question. THANKS in advance!!!
btw if anyone has a better 'title' for this question then please let me know.
I'm assuming you don't need to persist the status back to the database...
This is where you're having the problem:
<div>{{lesson.title}}: {{status}}</div>
You really don't need to store the status in your data model, because it's just used for presentation purposes.
Let's say your array of completed lessons is defined like this:
$scope.completedLessons = [1, 2, 3, 4, 5] // Or however you'd assign it
You need to create a function in your scope like this:
$scope.isLessonCompleted = function(lessonId) {
return $scope.completedLessons.indexOf(lessonId) > -1;
};
Then you need to change the html from above to this:
<div>{{lesson.title}}: {{isLessonCompleted(lesson.id) && 'Complete' || 'Incomplete'}}</div>
If lessons are also a model and each lesson should have a status, which isn't a column/field in your table but is something you'll add logic to determine, you could add a custom model accessor by adding the following to your models/Lesson.php:
// Append custom accessor attributes
protected $appends = ['status'];
public function getStatusAttribute() {
// Add logic here
return 'Complete';
}
This way, when you use Eloquent to retrieve your data, you'll also see a status attribute as part of the object, so you could then access it as usual $lesson->status (PHP) or lesson.status (JS).
For more information, see the official Laravel documentation on accessors and mutators
Previously I was using a json file with the following format:
[{"lat":43.788458853157117,"lng":-79.282781549043008,"category":"volunteer","name":"Rita","url":"", "description":"xxx is a member of 13"},{"lat":43.7,"lng":-79.4,"category":"organization","name":"TCAN","url":"http://tcan.ca","description":"Lorem ipsum"}]
Now I am attempting to generate the json file from a Drupal site and am getting the following structure. How can I reference the lowest level fields. I have looked at examples using d3.net but have not found any that apply.
{
"organizations": [
{
"member": {
"field_category": "organization",
"body": "A network of organizations in Toronto devoted to climate change mitigation and adaptation.",
"URL": "xxx.ca",
"title": "Toronto Climate Action Network",
"field_lat": 43.7,
"field_long": -79.4
}
},
{
"member": {
"field_category": "abc",
"body": "xxx.",
"URL": "",
"title": "yyy",
"field_lat": 43.7,
"field_long": -79.28
}
}
]
}
Assuming that your data is stored in the variable data:
var bottom = data.organizations.map(function(d) { return d.member; });
I'm having trouble finding a solution that will help me loop through a bunch of elements and putting the chosen values into a table. I've been able to withdraw some values but the method isn't dynamic.
Here is an example:
var Table = {
"credit": {
"link": "site link",
"logoUrl": "logo url",
"message": "message"
},
"groups": [
{
"labels": [
{
"name": "Western Conference",
"type": "conference"
},
{
"name": "Central Division",
"type": "division"
}
],
"standings": [
{
"stats": [
{
"name": "gp",
"value": 20
},
{
"name": "w",
"value": 17
},
{
"name": "l",
"value": 0
},
{
"name": "gf",
"value": 64
},
{
"name": "ga",
"value": 37
},
{
"name": "gd",
"value": 27
},
{
"name": "pts",
"value": 37
}
],
"team": {
"id": 12345,
"link": "team link",
"name": "team name",
"shortName": "team"
}
},
This is the structure of the elements. So far I've used this:
document.getElementById("sGamesPlayed").innerHTML=Table.groups[0].standings[0].stats[0].value;
to withdraw values. However there are more teams, stats and divisions so I would need some kind of loop to go through the elements and put the into a dynamic table.
I would consider you to look at http://underscorejs.org/.
it provides a bunch of utility functions that could help you,
for example, _.each() helps you loop through JSON properties.
for the sample objects you've given (after completing the missing brackets at the end),
_.each(Table.groups[0].standings[0].stats, function(stats){
console.log(stats['name']+","+stats['value'])
})
gives me:
gp,20
w,17
l,0
gf,64
ga,37
gd,27
pts,37
how it works is that you provide the object you want as the first argument and the function that you give as the second argument will be called with each element of the first argument (Assuming it is a list).
I would also urge you to look at underscore templating that you can use to render your table where i put the console.log :
http://net.tutsplus.com/tutorials/javascript-ajax/getting-cozy-with-underscore-js/
http://scriptble.com/2011/01/28/underscore-js-templates/
I guess your question is about filtering the values of the array standings. In order to do that you can use the jQuery grep function (if you want to use jQuery).
For example you can write:
var arr = $.grep(Table.groups[0].standings[0].stats, function(d){return d.value>25})
Which will give
arr = [{"name": "gf","value": 64}, {"name": "ga", "value": 37},{"name": "gd", "value": 27},{"name": "pts", "value": 37}]
If this is not what you meant, can you please create a jsFiddle with a sample of what you want?
Depending on what you want to do with the results, you can go over the object using a scheme like:
var groups, standings, stats, value;
groups = Table.groups;
// Do stuff with groups
for (var i=0, iLen=groups.length; i<iLen; i++) {
standings = groups[i].standings;
// Do stuff with standings
for (var j=0, jLen=standings.length; j<jLen; j++) {
stats = standings[j];
// Do stuff with stats
for (var k=0, kLen=stats.length; k<kLen; k++) {
value = stats[k].value;
// Do stuff with value
}
}
}
Of course I have no idea what the data is for, what the overall structure is or how you want to present it. But if you have deeply nested data, all you can do is dig into it. You might be able to write a recursive function, but it might also become very difficult to maintain if the data structure is complex.
I have a JSON object that is a nested array that is of the following form:
{
"name": "Math",
"children": [
{
"name": "Trigonometry",
"children": [
{
"name": "Right Triangles and an Introduction to Trigonometry",
"children": [
{
"name": "The Pythagorean Theorem",
"children": [
{
"name": "The Pythagorean Theorem",
"size": 30
},
{
"name": "Pythagorean Triples",
"size": 52
},
{
"name": "Converse of the Pythagorean Theorem",
"size": 13
}
]
}
]
}
]
},
{
"name": "Algebra",
"children": [
{
"name": "Equations and Functions",
"children": [
{
"name": "Variable Expressions",
"children": [
{
"name": "Evaluate Algebraic Expressions",
"size": 26
}
]
}
]
}
]
}
]
}
The full array is actually much larger and can be seen here. I'm using it to build interactive graphs and charts using D3.js (or perhaps other libraries). Because it's so large, I'd like to be able to split the array by branch. In other words, to carve out particular branches of the array.
For instance, is there a way to just pull out the node "Trigonometry" and all its children? Or "Algebra" and all its children? Then "Trigonometry" or "Algebra" would become the new root or parent node.
There is no built-in way to do something like this, although the comment about a JSON query language might give you the right work-around.
Really, the problem is that you have structured your data in a way that makes it very hard to use. If instead of
{
name: "key",
children: [...]
}
you just did
{
"key": [...]
}
then you could simply do myObject["key"] to get the array you want.
For example:
var math = {
"Trigonometry": {
"Right Triangles and an Introduction to Trigonometry": {
"The Pythagorean Theorem": {
"The Pythagorean Theorem": 30,
"Pythagorean Triples": 52,
"Converse of the Pythagorean Theorem": 13
}
}
},
"Algebra": {
"Equations and Functions": {
"Variable Expressions": {
"Evaluate Algebraic Expressions": 26
}
}
}
};
var trigonometry = math["Trigonometry"];
var expressionsAndFunctions = math["Algebra"]["Expressions and Functions"];
As a bonus, that's much shorter!
Array's splice function should do it. What that will do is remove the element at a given index and return it.
If you just want a shortcut to a specific branch, couldn't you also just use
var trig = tree['trigonometry'];
to get there. This wouldn't change the original object, buy will give you a simpler way to access nodes deep inside.