Last active
December 20, 2016 16:49
-
-
Save carvil/bad279fdced9f9f52e438cb9ae8a6274 to your computer and use it in GitHub Desktop.
Visualise the taxonomy using D3.js (tree view)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style type="text/css"> | |
.node { | |
cursor: pointer; | |
} | |
.overlay{ | |
background-color:#EEE; | |
} | |
.node circle { | |
fill: #fff; | |
stroke: steelblue; | |
stroke-width: 1.5px; | |
} | |
.node text { | |
font-size:10px; | |
font-family:sans-serif; | |
} | |
.link { | |
fill: none; | |
stroke: #ccc; | |
stroke-width: 1.5px; | |
} | |
.templink { | |
fill: none; | |
stroke: red; | |
stroke-width: 3px; | |
} | |
.ghostCircle.show{ | |
display:block; | |
} | |
.ghostCircle, .activeDrag .ghostCircle{ | |
display: none; | |
} | |
</style> | |
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="taxonTree.js"></script> | |
<body> | |
<p>Tree</p> | |
<div id="tree-container"></div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$(document).ready(function() { | |
// Get JSON data | |
treeData = { | |
"name": "Education, training and skills", | |
"parents": [ | |
], | |
"children": [ | |
{ | |
"name": "School education from 5 to 18 years", | |
"parents": [ | |
"Education, training and skills" | |
], | |
"children": [ | |
{ | |
"name": "School curriculum, assessments and performance", | |
"parents": [ | |
"School education from 5 to 18 years" | |
], | |
"children": [ | |
{ | |
"name": "Primary curriculum, key stage 1", | |
"parents": [ | |
"School curriculum, assessments and performance" | |
], | |
"children": [ | |
{ | |
"name": "Phonics", | |
"parents": [ | |
"Early years curriculum from birth to 5 years", | |
"Primary curriculum, key stage 1" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 81, | |
"number_of_tagged_guidance_content": 54 | |
}, | |
{ | |
"name": "Assessments", | |
"parents": [ | |
"Primary curriculum, key stage 1" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 19, | |
"number_of_tagged_guidance_content": 19 | |
}, | |
{ | |
"name": "English", | |
"parents": [ | |
"Primary curriculum, key stage 1" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 13, | |
"number_of_tagged_guidance_content": 13 | |
}, | |
{ | |
"name": "Maths", | |
"parents": [ | |
"Primary curriculum, key stage 1" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 6, | |
"number_of_tagged_guidance_content": 6 | |
}, | |
{ | |
"name": "Programmes of study", | |
"parents": [ | |
"Primary curriculum, key stage 1" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 11, | |
"number_of_tagged_guidance_content": 11 | |
}, | |
{ | |
"name": "Science", | |
"parents": [ | |
"Primary curriculum, key stage 1" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 1, | |
"number_of_tagged_guidance_content": 1 | |
}, | |
{ | |
"name": "Tests", | |
"parents": [ | |
"Primary curriculum, key stage 1" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 17, | |
"number_of_tagged_guidance_content": 17 | |
} | |
], | |
"number_of_tagged_content": 208, | |
"number_of_tagged_guidance_content": 83 | |
}, | |
{ | |
"name": "Primary curriculum, key stage 2", | |
"parents": [ | |
"School curriculum, assessments and performance" | |
], | |
"children": [ | |
{ | |
"name": "Phonics", | |
"parents": [ | |
"Primary curriculum, key stage 2" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Assessments", | |
"parents": [ | |
"Primary curriculum, key stage 2" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 9, | |
"number_of_tagged_guidance_content": 9 | |
}, | |
{ | |
"name": "English", | |
"parents": [ | |
"Primary curriculum, key stage 2" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 14, | |
"number_of_tagged_guidance_content": 14 | |
}, | |
{ | |
"name": "Maths", | |
"parents": [ | |
"Primary curriculum, key stage 2" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 6, | |
"number_of_tagged_guidance_content": 6 | |
}, | |
{ | |
"name": "Programmes of study", | |
"parents": [ | |
"Primary curriculum, key stage 2" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 11, | |
"number_of_tagged_guidance_content": 11 | |
}, | |
{ | |
"name": "Science", | |
"parents": [ | |
"Primary curriculum, key stage 2" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Tests", | |
"parents": [ | |
"Primary curriculum, key stage 2" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 32, | |
"number_of_tagged_guidance_content": 32 | |
} | |
], | |
"number_of_tagged_content": 7, | |
"number_of_tagged_guidance_content": 7 | |
}, | |
{ | |
"name": "Secondary curriculum, key stage 3 and key stage 4", | |
"parents": [ | |
"School curriculum, assessments and performance" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Spiritual, moral, social and cultural development", | |
"parents": [ | |
"School curriculum, assessments and performance" | |
], | |
"children": [ | |
{ | |
"name": "Cultural education", | |
"parents": [ | |
"Spiritual, moral, social and cultural development" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Religious education", | |
"parents": [ | |
"Spiritual, moral, social and cultural development" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Promoting British values and citizenship in schools", | |
"parents": [ | |
"Spiritual, moral, social and cultural development" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Personal, social, health and economic education", | |
"parents": [ | |
"School curriculum, assessments and performance" | |
], | |
"children": [ | |
{ | |
"name": "Sex and relationship education", | |
"parents": [ | |
"Personal, social, health and economic education" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Physical education", | |
"parents": [ | |
"School curriculum, assessments and performance" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Administration of exams and tests in schools", | |
"parents": [ | |
"School curriculum, assessments and performance" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Key stage 5, AS and A Levels", | |
"parents": [ | |
"School curriculum, assessments and performance" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 28, | |
"number_of_tagged_guidance_content": 2 | |
}, | |
{ | |
"name": "Governing and managing schools", | |
"parents": [ | |
"School education from 5 to 18 years" | |
], | |
"children": [ | |
{ | |
"name": "Managing school data", | |
"parents": [ | |
"Governing and managing schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 14, | |
"number_of_tagged_guidance_content": 14 | |
}, | |
{ | |
"name": "Copyright for schools", | |
"parents": [ | |
"Governing and managing schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Procurement for schools", | |
"parents": [ | |
"Governing and managing schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "School buildings and premises", | |
"parents": [ | |
"Governing and managing schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 134, | |
"number_of_tagged_guidance_content": 45 | |
}, | |
{ | |
"name": "Setting up or shutting down a school", | |
"parents": [ | |
"Governing and managing schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Changing the status of a school", | |
"parents": [ | |
"Governing and managing schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Dealing with complaints about a school", | |
"parents": [ | |
"Governing and managing schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 2, | |
"number_of_tagged_guidance_content": 2 | |
}, | |
{ | |
"name": "Whistleblowing in schools", | |
"parents": [ | |
"Governing and managing schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "School insurance and risk management", | |
"parents": [ | |
"Governing and managing schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 21, | |
"number_of_tagged_guidance_content": 16 | |
}, | |
{ | |
"name": "School governance", | |
"parents": [ | |
"Governing and managing schools" | |
], | |
"children": [ | |
{ | |
"name": "Governance partnerships for multiple schools", | |
"parents": [ | |
"School governance" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Pupil participation in school governance", | |
"parents": [ | |
"School governance" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Recruiting and managing school staff", | |
"parents": [ | |
"Governing and managing schools", | |
"Teachers and school staff" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 12, | |
"number_of_tagged_guidance_content": 8 | |
} | |
], | |
"number_of_tagged_content": 46, | |
"number_of_tagged_guidance_content": 25 | |
}, | |
{ | |
"name": "Teachers and school staff", | |
"parents": [ | |
"School education from 5 to 18 years" | |
], | |
"children": [ | |
{ | |
"name": "Recruiting and managing school staff", | |
"parents": [ | |
"Governing and managing schools", | |
"Teachers and school staff" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 12, | |
"number_of_tagged_guidance_content": 8 | |
}, | |
{ | |
"name": "Teaching standards, conduct and practice", | |
"parents": [ | |
"Teachers and school staff" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Teacher records", | |
"parents": [ | |
"Teachers and school staff" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Teacher pay and conditions", | |
"parents": [ | |
"Teachers and school staff" | |
], | |
"children": [ | |
{ | |
"name": "Teacher pensions", | |
"parents": [ | |
"Teacher pay and conditions" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Teacher training and professional development", | |
"parents": [ | |
"Teachers and school staff" | |
], | |
"children": [ | |
{ | |
"name": "Qualified Teacher Status (QTS)", | |
"parents": [ | |
"Teacher training and professional development" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Initial Teacher Training (ITT)", | |
"parents": [ | |
"Teacher training and professional development" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Subject Knowledge Enhancement (SKE)", | |
"parents": [ | |
"Teacher training and professional development" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "National Professional Qualification for Headship (NPQH)", | |
"parents": [ | |
"Teacher training and professional development" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Extra-curricular activities for schools", | |
"parents": [ | |
"School education from 5 to 18 years" | |
], | |
"children": [ | |
{ | |
"name": "School trips", | |
"parents": [ | |
"Extra-curricular activities for schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "School links with home, community and business", | |
"parents": [ | |
"School education from 5 to 18 years" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "School behaviour and attendance", | |
"parents": [ | |
"School education from 5 to 18 years" | |
], | |
"children": [ | |
{ | |
"name": "School discipline and exclusions", | |
"parents": [ | |
"School behaviour and attendance" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "School leaving age", | |
"parents": [ | |
"School behaviour and attendance" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "School bullying", | |
"parents": [ | |
"School behaviour and attendance" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Equality and diversity in schools", | |
"parents": [ | |
"School behaviour and attendance" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "School absence and truancy", | |
"parents": [ | |
"School behaviour and attendance" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Careers guidance in schools", | |
"parents": [ | |
"School education from 5 to 18 years" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "School admissions and pupil censuses", | |
"parents": [ | |
"School education from 5 to 18 years" | |
], | |
"children": [ | |
{ | |
"name": "Access to education for minority groups", | |
"parents": [ | |
"School admissions and pupil censuses" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "School meals, transport and uniform", | |
"parents": [ | |
"School education from 5 to 18 years" | |
], | |
"children": [ | |
{ | |
"name": "School meals", | |
"parents": [ | |
"School meals, transport and uniform" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "School transport", | |
"parents": [ | |
"School meals, transport and uniform" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "School uniform", | |
"parents": [ | |
"School meals, transport and uniform" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Health, safety and pupil wellbeing", | |
"parents": [ | |
"School education from 5 to 18 years" | |
], | |
"children": [ | |
{ | |
"name": "Safeguarding pupils", | |
"parents": [ | |
"Health, safety and pupil wellbeing" | |
], | |
"children": [ | |
{ | |
"name": "Prevent duty for schools", | |
"parents": [ | |
"Safeguarding pupils" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "e-safety", | |
"parents": [ | |
"Safeguarding pupils" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Alternatives to school", | |
"parents": [ | |
"School education from 5 to 18 years" | |
], | |
"children": [ | |
{ | |
"name": "Alternative provision and Pupil Referral Units", | |
"parents": [ | |
"Alternatives to school" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Home schooling", | |
"parents": [ | |
"Alternatives to school" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "School inspections", | |
"parents": [ | |
"School education from 5 to 18 years" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 42, | |
"number_of_tagged_guidance_content": 10 | |
}, | |
{ | |
"name": "Early years curriculum from birth to 5 years", | |
"parents": [ | |
"Education, training and skills", | |
"Running a childcare business" | |
], | |
"children": [ | |
{ | |
"name": "Phonics", | |
"parents": [ | |
"Early years curriculum from birth to 5 years", | |
"Primary curriculum, key stage 1" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 81, | |
"number_of_tagged_guidance_content": 54 | |
} | |
], | |
"number_of_tagged_content": 112, | |
"number_of_tagged_guidance_content": 30 | |
}, | |
{ | |
"name": "Funding and finance for education providers", | |
"parents": [ | |
"Education, training and skills" | |
], | |
"children": [ | |
{ | |
"name": "Funding and finance for schools", | |
"parents": [ | |
"Funding and finance for education providers" | |
], | |
"children": [ | |
{ | |
"name": "16 to 19 funding", | |
"parents": [ | |
"Funding and finance for schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Pupil premium", | |
"parents": [ | |
"Funding and finance for schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 33, | |
"number_of_tagged_guidance_content": 9 | |
}, | |
{ | |
"name": "Schools forums", | |
"parents": [ | |
"Funding and finance for schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 180, | |
"number_of_tagged_guidance_content": 65 | |
}, | |
{ | |
"name": "Funding and finance for further education providers", | |
"parents": [ | |
"Funding and finance for education providers" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Funding for special educational needs and disability support", | |
"parents": [ | |
"Funding and finance for education providers" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 12, | |
"number_of_tagged_guidance_content": 1 | |
}, | |
{ | |
"name": "Further education, skills and vocational training", | |
"parents": [ | |
"Education, training and skills" | |
], | |
"children": [ | |
{ | |
"name": "Adult and community learning", | |
"parents": [ | |
"Further education, skills and vocational training" | |
], | |
"children": [ | |
{ | |
"name": "Basic skills education", | |
"parents": [ | |
"Adult and community learning" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Apprenticeships, traineeships and internships", | |
"parents": [ | |
"Further education, skills and vocational training" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Further education, courses and qualifications", | |
"parents": [ | |
"Further education, skills and vocational training" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Inspection and performance of further education providers", | |
"parents": [ | |
"Further education, skills and vocational training" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "University and higher education", | |
"parents": [ | |
"Education, training and skills" | |
], | |
"children": [ | |
{ | |
"name": "Higher education courses and qualifications", | |
"parents": [ | |
"University and higher education" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Governance and management for higher education institutions", | |
"parents": [ | |
"University and higher education" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Funding and finance for students", | |
"parents": [ | |
"Education, training and skills" | |
], | |
"children": [ | |
{ | |
"name": "Student loans", | |
"parents": [ | |
"Funding and finance for students" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Student sponsorship", | |
"parents": [ | |
"Funding and finance for students" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Financial help for students who are parents", | |
"parents": [ | |
"Funding and finance for students" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Financial help for international students in the UK", | |
"parents": [ | |
"Funding and finance for students" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Students with special needs, disabilities or disadvantages", | |
"parents": [ | |
"Education, training and skills" | |
], | |
"children": [ | |
{ | |
"name": "Able, gifted and talented pupils", | |
"parents": [ | |
"Students with special needs, disabilities or disadvantages" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Special educational needs and disability support in schools", | |
"parents": [ | |
"Students with special needs, disabilities or disadvantages" | |
], | |
"children": [ | |
{ | |
"name": "Assessing pupils with special educational needs", | |
"parents": [ | |
"Special educational needs and disability support in schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "SEND code of practice", | |
"parents": [ | |
"Special educational needs and disability support in schools" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Vulnerable and disadvantaged pupils", | |
"parents": [ | |
"Students with special needs, disabilities or disadvantages" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Funding for special educational needs and disability", | |
"parents": [ | |
"Students with special needs, disabilities or disadvantages" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
}, | |
{ | |
"name": "Support for education work in other countries", | |
"parents": [ | |
"Education, training and skills" | |
], | |
"children": [ | |
], | |
"number_of_tagged_content": 0, | |
"number_of_tagged_guidance_content": 0 | |
} | |
], | |
"number_of_tagged_content": 29, | |
"number_of_tagged_guidance_content": 0 | |
} | |
// Calculate total nodes, max label length | |
var totalNodes = 0; | |
var maxLabelLength = 0; | |
// variables for drag/drop | |
var selectedNode = null; | |
var draggingNode = null; | |
// panning variables | |
var panSpeed = 200; | |
var panBoundary = 20; // Within 20px from edges will pan when dragging. | |
// Misc. variables | |
var i = 0; | |
var duration = 750; | |
var root; | |
// size of the diagram | |
var viewerWidth = 1448; //$(document).width(); | |
var viewerHeight = 815; //$(document).height(); | |
var tree = d3.layout.tree() | |
.size([viewerHeight, viewerWidth]); | |
// define a d3 diagonal projection for use by the node paths later on. | |
var diagonal = d3.svg.diagonal() | |
.projection(function(d) { | |
return [d.y, d.x]; | |
}); | |
// A recursive helper function for performing some setup by walking through all nodes | |
function visit(parent, visitFn, childrenFn) { | |
if (!parent) return; | |
visitFn(parent); | |
var children = childrenFn(parent); | |
if (children) { | |
var count = children.length; | |
for (var i = 0; i < count; i++) { | |
visit(children[i], visitFn, childrenFn); | |
} | |
} | |
} | |
// Call visit function to establish maxLabelLength | |
visit(treeData, function(d) { | |
collapse(d); | |
totalNodes++; | |
maxLabelLength = Math.max(d.name.length, maxLabelLength); | |
}, function(d) { | |
return d.children && d.children.length > 0 ? d.children : null; | |
}); | |
// sort the tree according to the node names | |
function sortTree() { | |
tree.sort(function(a, b) { | |
return b.name.toLowerCase() < a.name.toLowerCase() ? 1 : -1; | |
}); | |
} | |
// Sort the tree initially incase the JSON isn't in a sorted order. | |
sortTree(); | |
// TODO: Pan function, can be better implemented. | |
function pan(domNode, direction) { | |
var speed = panSpeed; | |
if (panTimer) { | |
clearTimeout(panTimer); | |
translateCoords = d3.transform(svgGroup.attr("transform")); | |
if (direction == 'left' || direction == 'right') { | |
translateX = direction == 'left' ? translateCoords.translate[0] + speed : translateCoords.translate[0] - speed; | |
translateY = translateCoords.translate[1]; | |
} else if (direction == 'up' || direction == 'down') { | |
translateX = translateCoords.translate[0]; | |
translateY = direction == 'up' ? translateCoords.translate[1] + speed : translateCoords.translate[1] - speed; | |
} | |
scaleX = translateCoords.scale[0]; | |
scaleY = translateCoords.scale[1]; | |
scale = zoomListener.scale(); | |
svgGroup.transition().attr("transform", "translate(" + translateX + "," + translateY + ")scale(" + scale + ")"); | |
d3.select(domNode).select('g.node').attr("transform", "translate(" + translateX + "," + translateY + ")"); | |
zoomListener.scale(zoomListener.scale()); | |
zoomListener.translate([translateX, translateY]); | |
panTimer = setTimeout(function() { | |
pan(domNode, speed, direction); | |
}, 50); | |
} | |
} | |
// Define the zoom function for the zoomable tree | |
function zoom() { | |
svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); | |
} | |
// define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents | |
var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", zoom); | |
function initiateDrag(d, domNode) { | |
draggingNode = d; | |
d3.select(domNode).select('.ghostCircle').attr('pointer-events', 'none'); | |
d3.selectAll('.ghostCircle').attr('class', 'ghostCircle show'); | |
d3.select(domNode).attr('class', 'node activeDrag'); | |
svgGroup.selectAll("g.node").sort(function(a, b) { // select the parent and sort the path's | |
if (a.id != draggingNode.id) return 1; // a is not the hovered element, send "a" to the back | |
else return -1; // a is the hovered element, bring "a" to the front | |
}); | |
// if nodes has children, remove the links and nodes | |
if (nodes.length > 1) { | |
// remove link paths | |
links = tree.links(nodes); | |
nodePaths = svgGroup.selectAll("path.link") | |
.data(links, function(d) { | |
return d.target.id; | |
}).remove(); | |
// remove child nodes | |
nodesExit = svgGroup.selectAll("g.node") | |
.data(nodes, function(d) { | |
return d.id; | |
}).filter(function(d, i) { | |
if (d.id == draggingNode.id) { | |
return false; | |
} | |
return true; | |
}).remove(); | |
} | |
// remove parent link | |
parentLink = tree.links(tree.nodes(draggingNode.parent)); | |
svgGroup.selectAll('path.link').filter(function(d, i) { | |
if (d.target.id == draggingNode.id) { | |
return true; | |
} | |
return false; | |
}).remove(); | |
dragStarted = null; | |
} | |
// define the baseSvg, attaching a class for styling and the zoomListener | |
var baseSvg = d3.select("#tree-container").append("svg") | |
.attr("width", viewerWidth) | |
.attr("height", viewerHeight) | |
.attr("class", "overlay") | |
.call(zoomListener); | |
// Define the drag listeners for drag/drop behaviour of nodes. | |
dragListener = d3.behavior.drag() | |
.on("dragstart", function(d) { | |
if (d == root) { | |
return; | |
} | |
dragStarted = true; | |
nodes = tree.nodes(d); | |
d3.event.sourceEvent.stopPropagation(); | |
// it's important that we suppress the mouseover event on the node being dragged. Otherwise it will absorb the mouseover event and the underlying node will not detect it d3.select(this).attr('pointer-events', 'none'); | |
}) | |
.on("drag", function(d) { | |
if (d == root) { | |
return; | |
} | |
if (dragStarted) { | |
domNode = this; | |
initiateDrag(d, domNode); | |
} | |
// get coords of mouseEvent relative to svg container to allow for panning | |
relCoords = d3.mouse($('svg').get(0)); | |
if (relCoords[0] < panBoundary) { | |
panTimer = true; | |
pan(this, 'left'); | |
} else if (relCoords[0] > ($('svg').width() - panBoundary)) { | |
panTimer = true; | |
pan(this, 'right'); | |
} else if (relCoords[1] < panBoundary) { | |
panTimer = true; | |
pan(this, 'up'); | |
} else if (relCoords[1] > ($('svg').height() - panBoundary)) { | |
panTimer = true; | |
pan(this, 'down'); | |
} else { | |
try { | |
clearTimeout(panTimer); | |
} catch (e) { | |
} | |
} | |
d.x0 += d3.event.dy; | |
d.y0 += d3.event.dx; | |
var node = d3.select(this); | |
node.attr("transform", "translate(" + d.y0 + "," + d.x0 + ")"); | |
updateTempConnector(); | |
}).on("dragend", function(d) { | |
if (d == root) { | |
return; | |
} | |
domNode = this; | |
if (selectedNode) { | |
// now remove the element from the parent, and insert it into the new elements children | |
var index = draggingNode.parent.children.indexOf(draggingNode); | |
if (index > -1) { | |
draggingNode.parent.children.splice(index, 1); | |
} | |
if (typeof selectedNode.children !== 'undefined' || typeof selectedNode._children !== 'undefined') { | |
if (typeof selectedNode.children !== 'undefined') { | |
selectedNode.children.push(draggingNode); | |
} else { | |
selectedNode._children.push(draggingNode); | |
} | |
} else { | |
selectedNode.children = []; | |
selectedNode.children.push(draggingNode); | |
} | |
// Make sure that the node being added to is expanded so user can see added node is correctly moved | |
expand(selectedNode); | |
sortTree(); | |
endDrag(); | |
} else { | |
endDrag(); | |
} | |
}); | |
function endDrag() { | |
selectedNode = null; | |
d3.selectAll('.ghostCircle').attr('class', 'ghostCircle'); | |
d3.select(domNode).attr('class', 'node'); | |
// now restore the mouseover event or we won't be able to drag a 2nd time | |
d3.select(domNode).select('.ghostCircle').attr('pointer-events', ''); | |
updateTempConnector(); | |
if (draggingNode !== null) { | |
update(root); | |
centerNode(draggingNode); | |
draggingNode = null; | |
} | |
} | |
// Helper functions for collapsing and expanding nodes. | |
function collapse(d) { | |
if (d.children) { | |
d._children = d.children; | |
d._children.forEach(collapse); | |
d.children = null; | |
} | |
} | |
function expand(d) { | |
if (d._children) { | |
d.children = d._children; | |
d.children.forEach(expand); | |
d._children = null; | |
} | |
} | |
var overCircle = function(d) { | |
selectedNode = d; | |
updateTempConnector(); | |
}; | |
var outCircle = function(d) { | |
selectedNode = null; | |
updateTempConnector(); | |
}; | |
// Function to update the temporary connector indicating dragging affiliation | |
var updateTempConnector = function() { | |
var data = []; | |
if (draggingNode !== null && selectedNode !== null) { | |
// have to flip the source coordinates since we did this for the existing connectors on the original tree | |
data = [{ | |
source: { | |
x: selectedNode.y0, | |
y: selectedNode.x0 | |
}, | |
target: { | |
x: draggingNode.y0, | |
y: draggingNode.x0 | |
} | |
}]; | |
} | |
var link = svgGroup.selectAll(".templink").data(data); | |
link.enter().append("path") | |
.attr("class", "templink") | |
.attr("d", d3.svg.diagonal()) | |
.attr('pointer-events', 'none'); | |
link.attr("d", d3.svg.diagonal()); | |
link.exit().remove(); | |
}; | |
// Function to center node when clicked/dropped so node doesn't get lost when collapsing/moving with large amount of children. | |
function centerNode(source) { | |
scale = zoomListener.scale(); | |
x = -source.y0; | |
y = -source.x0; | |
x = x * scale + viewerWidth / 2; | |
y = y * scale + viewerHeight / 2; | |
d3.select('g').transition() | |
.duration(duration) | |
.attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")"); | |
zoomListener.scale(scale); | |
zoomListener.translate([x, y]); | |
} | |
// Toggle children function | |
function toggleChildren(d) { | |
if (d.children) { | |
d._children = d.children; | |
d.children = null; | |
} else if (d._children) { | |
d.children = d._children; | |
d._children = null; | |
} | |
return d; | |
} | |
// Toggle children on click. | |
function click(d) { | |
if (d3.event.defaultPrevented) return; // click suppressed | |
d = toggleChildren(d); | |
update(d); | |
centerNode(d); | |
} | |
function update(source) { | |
// Compute the new height, function counts total children of root node and sets tree height accordingly. | |
// This prevents the layout looking squashed when new nodes are made visible or looking sparse when nodes are removed | |
// This makes the layout more consistent. | |
var levelWidth = [1]; | |
var childCount = function(level, n) { | |
if (n.children && n.children.length > 0) { | |
if (levelWidth.length <= level + 1) levelWidth.push(0); | |
levelWidth[level + 1] += n.children.length; | |
n.children.forEach(function(d) { | |
childCount(level + 1, d); | |
}); | |
} | |
}; | |
childCount(0, root); | |
var newHeight = d3.max(levelWidth) * 25; // 25 pixels per line | |
tree = tree.size([newHeight, viewerWidth]); | |
// Compute the new tree layout. | |
var nodes = tree.nodes(root).reverse(), | |
links = tree.links(nodes); | |
// Set widths between levels based on maxLabelLength. | |
nodes.forEach(function(d) { | |
d.y = (d.depth * (maxLabelLength * 10)); //maxLabelLength * 10px | |
// alternatively to keep a fixed scale one can set a fixed depth per level | |
// Normalize for fixed-depth by commenting out below line | |
// d.y = (d.depth * 500); //500px per level. | |
}); | |
// Update the nodes… | |
node = svgGroup.selectAll("g.node") | |
.data(nodes, function(d) { | |
return d.id || (d.id = ++i); | |
}); | |
// Enter any new nodes at the parent's previous position. | |
var nodeEnter = node.enter().append("g") | |
.call(dragListener) | |
.attr("class", "node") | |
.attr("transform", function(d) { | |
return "translate(" + source.y0 + "," + source.x0 + ")"; | |
}) | |
.on('click', click); | |
nodeEnter.append("circle") | |
.attr('class', 'nodeCircle') | |
.attr("r", 0) | |
.style("fill", function(d) { | |
return d._children ? "lightsteelblue" : "#fff"; | |
}); | |
nodeEnter.append("text") | |
.attr("x", function(d) { | |
return d.children || d._children ? -10 : 10; | |
}) | |
.attr("dy", ".35em") | |
.attr('class', 'nodeText') | |
.attr("text-anchor", function(d) { | |
return d.children || d._children ? "end" : "start"; | |
}) | |
.text(function(d) { | |
return d.name; | |
}) | |
.style("fill-opacity", 0); | |
// phantom node to give us mouseover in a radius around it | |
nodeEnter.append("circle") | |
.attr('class', 'ghostCircle') | |
.attr("r", 30) | |
.attr("opacity", 0.2) // change this to zero to hide the target area | |
.style("fill", "red") | |
.attr('pointer-events', 'mouseover') | |
.on("mouseover", function(node) { | |
overCircle(node); | |
}) | |
.on("mouseout", function(node) { | |
outCircle(node); | |
}); | |
// Update the text to reflect whether node has children or not. | |
node.select('text') | |
.attr("x", function(d) { | |
return d.children || d._children ? -10 : 10; | |
}) | |
.attr("text-anchor", function(d) { | |
return d.children || d._children ? "end" : "start"; | |
}) | |
.text(function(d) { | |
return d.name; | |
}); | |
// Change the circle fill depending on whether it has children and is collapsed | |
node.select("circle.nodeCircle") | |
.attr("r", 4.5) | |
.style("fill", function(d) { | |
return d._children ? "lightsteelblue" : "#fff"; | |
}); | |
// Transition nodes to their new position. | |
var nodeUpdate = node.transition() | |
.duration(duration) | |
.attr("transform", function(d) { | |
return "translate(" + d.y + "," + d.x + ")"; | |
}); | |
// Fade the text in | |
nodeUpdate.select("text") | |
.style("fill-opacity", 1); | |
// Transition exiting nodes to the parent's new position. | |
var nodeExit = node.exit().transition() | |
.duration(duration) | |
.attr("transform", function(d) { | |
return "translate(" + source.y + "," + source.x + ")"; | |
}) | |
.remove(); | |
nodeExit.select("circle") | |
.attr("r", 0); | |
nodeExit.select("text") | |
.style("fill-opacity", 0); | |
// Update the links… | |
var link = svgGroup.selectAll("path.link") | |
.data(links, function(d) { | |
return d.target.id; | |
}); | |
// Enter any new links at the parent's previous position. | |
link.enter().insert("path", "g") | |
.attr("class", "link") | |
.attr("d", function(d) { | |
var o = { | |
x: source.x0, | |
y: source.y0 | |
}; | |
return diagonal({ | |
source: o, | |
target: o | |
}); | |
}); | |
// Transition links to their new position. | |
link.transition() | |
.duration(duration) | |
.attr("d", diagonal); | |
// Transition exiting nodes to the parent's new position. | |
link.exit().transition() | |
.duration(duration) | |
.attr("d", function(d) { | |
var o = { | |
x: source.x, | |
y: source.y | |
}; | |
return diagonal({ | |
source: o, | |
target: o | |
}); | |
}) | |
.remove(); | |
// Stash the old positions for transition. | |
nodes.forEach(function(d) { | |
d.x0 = d.x; | |
d.y0 = d.y; | |
}); | |
} | |
// Append a group which holds all nodes and which the zoom Listener can act upon. | |
var svgGroup = baseSvg.append("g"); | |
// Define the root | |
root = treeData; | |
root.x0 = viewerHeight / 2; | |
root.y0 = 0; | |
// Layout the tree initially and center on the root node. | |
update(root); | |
centerNode(root); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment