Github template for vida.io
Node and gulp are required. To run, use command: gulp
Access through browser at http://localhost:5000.
Describe your document in manifest.json. Format is as follows:
{
"data": ["document.json"],
"javascript": ["document.js"],
"stylesheet": ["document.css"],
"html": ["document.html"],
"properties": [
{"label":"Data Column 0 (X Axis)","name":"data0","type":"data_column","value":null},
{"label":"Data Column 1 (Y Axis)","name":"data1","type":"data_column","value":null},
{"label":"Label 0","name":"label0","type":"string","value":"label 0"},
{"label":"Label 1","name":"label1","type":"string","value":"label 1"},
{"label":"Color 0","name":"color0","type":"color","value":"#0f608b"},
{"label":"Color 1","name":"color1","type":"color","value":"#99ccff"},
{"label":"Width","name":"width","type":"number","value":800},
{"label":"Height","name":"height","type":"number","value":400}
]
}
data: list of data files for your document
javascript: list of javascript files for your document
stylesheet: list of stylesheet files for your document
html: list of html files for your document
properties: external properties for vida.io user interface
properties.label: property label
properties.name: property name
properties.type: property type (string/number/boolean/color/data_column)
properties.value: default property value
Use sourceURL to enable debugging in Chrome:
//# sourceURL=document.js
Copyright Vida Lab Inc. 2014
License: BSD
<!-- output: ../index.html-->
<html>
<head>
<meta charset="UTF-8"/>
<title>Vida Lab Template</title>
<meta name="Description" content="Vida Lab Template"/>
<meta name="Keywords" content="Vida Lab Template"/>
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Lato:400,700"/>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"/>
<script type="text/javascript" src="d3.js"></script>
<script type="text/javascript" src="//code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript" src="vida_template.js"></script>
</head>
<body>
<div id="canvas"></div>
</body>
</html>
/*--- IMPORTANT GUIDELINES ---
1. Use CSS styling
2. Use class or id specific to style elements related the visualization only
3. Avoid using styling that alters this webapp (Example: html, body, h1, a, etc.).
Documents may get flagged if doing so ---*/
#canvas {
}
#canvas-svg {
}
.link {
stroke: #999;
stroke-opacity: 1;
}
circle.force-circle {
stroke: #fff;
stroke-width: 1.5px;
}
text.force-text {
fill: #000;
font: 10px sans-serif;
pointer-events: none;
}
source,target,sourceLabel,targetLabel
1,0,Napoleon,Myriel
2,0,Mlle.Baptistine,Myriel
3,0,Mme.Magloire,Myriel
3,2,Mme.Magloire,Mlle.Baptistine
4,0,CountessdeLo,Myriel
5,0,Geborand,Myriel
6,0,Champtercier,Myriel
7,0,Cravatte,Myriel
8,0,Count,Myriel
9,0,OldMan,Myriel
11,10,Valjean,Labarre
11,3,Valjean,Mme.Magloire
11,2,Valjean,Mlle.Baptistine
11,0,Valjean,Myriel
12,11,Marguerite,Valjean
13,11,Mme.deR,Valjean
14,11,Isabeau,Valjean
15,11,Gervais,Valjean
17,16,Listolier,Tholomyes
18,16,Fameuil,Tholomyes
18,17,Fameuil,Listolier
19,16,Blacheville,Tholomyes
19,17,Blacheville,Listolier
19,18,Blacheville,Fameuil
20,16,Favourite,Tholomyes
20,17,Favourite,Listolier
20,18,Favourite,Fameuil
20,19,Favourite,Blacheville
21,16,Dahlia,Tholomyes
21,17,Dahlia,Listolier
21,18,Dahlia,Fameuil
21,19,Dahlia,Blacheville
21,20,Dahlia,Favourite
22,16,Zephine,Tholomyes
22,17,Zephine,Listolier
22,18,Zephine,Fameuil
22,19,Zephine,Blacheville
22,20,Zephine,Favourite
22,21,Zephine,Dahlia
23,16,Fantine,Tholomyes
23,17,Fantine,Listolier
23,18,Fantine,Fameuil
23,19,Fantine,Blacheville
23,20,Fantine,Favourite
23,21,Fantine,Dahlia
23,22,Fantine,Zephine
23,12,Fantine,Marguerite
23,11,Fantine,Valjean
24,23,Mme.Thenardier,Fantine
24,11,Mme.Thenardier,Valjean
25,24,Thenardier,Mme.Thenardier
25,23,Thenardier,Fantine
25,11,Thenardier,Valjean
26,24,Cosette,Mme.Thenardier
26,11,Cosette,Valjean
26,16,Cosette,Tholomyes
26,25,Cosette,Thenardier
27,11,Javert,Valjean
27,23,Javert,Fantine
27,25,Javert,Thenardier
27,24,Javert,Mme.Thenardier
27,26,Javert,Cosette
28,11,Fauchelevent,Valjean
28,27,Fauchelevent,Javert
29,23,Bamatabois,Fantine
29,27,Bamatabois,Javert
29,11,Bamatabois,Valjean
30,23,Perpetue,Fantine
31,30,Simplice,Perpetue
31,11,Simplice,Valjean
31,23,Simplice,Fantine
31,27,Simplice,Javert
32,11,Scaufflaire,Valjean
33,11,Woman1,Valjean
33,27,Woman1,Javert
34,11,Judge,Valjean
34,29,Judge,Bamatabois
35,11,Champmathieu,Valjean
35,34,Champmathieu,Judge
35,29,Champmathieu,Bamatabois
36,34,Brevet,Judge
36,35,Brevet,Champmathieu
36,11,Brevet,Valjean
36,29,Brevet,Bamatabois
37,34,Chenildieu,Judge
37,35,Chenildieu,Champmathieu
37,36,Chenildieu,Brevet
37,11,Chenildieu,Valjean
37,29,Chenildieu,Bamatabois
38,34,Cochepaille,Judge
38,35,Cochepaille,Champmathieu
38,36,Cochepaille,Brevet
38,37,Cochepaille,Chenildieu
38,11,Cochepaille,Valjean
38,29,Cochepaille,Bamatabois
39,25,Pontmercy,Thenardier
40,25,Boulatruelle,Thenardier
41,24,Eponine,Mme.Thenardier
41,25,Eponine,Thenardier
42,41,Anzelma,Eponine
42,25,Anzelma,Thenardier
42,24,Anzelma,Mme.Thenardier
43,11,Woman2,Valjean
43,26,Woman2,Cosette
43,27,Woman2,Javert
44,28,MotherInnocent,Fauchelevent
44,11,MotherInnocent,Valjean
45,28,Gribier,Fauchelevent
47,46,Mme.Burgon,Jondrette
48,47,Gavroche,Mme.Burgon
48,25,Gavroche,Thenardier
48,27,Gavroche,Javert
48,11,Gavroche,Valjean
49,26,Gillenormand,Cosette
49,11,Gillenormand,Valjean
50,49,Magnon,Gillenormand
50,24,Magnon,Mme.Thenardier
51,49,Mlle.Gillenormand,Gillenormand
51,26,Mlle.Gillenormand,Cosette
51,11,Mlle.Gillenormand,Valjean
52,51,Mme.Pontmercy,Mlle.Gillenormand
52,39,Mme.Pontmercy,Pontmercy
53,51,Mlle.Vaubois,Mlle.Gillenormand
54,51,Lt.Gillenormand,Mlle.Gillenormand
54,49,Lt.Gillenormand,Gillenormand
54,26,Lt.Gillenormand,Cosette
55,51,Marius,Mlle.Gillenormand
55,49,Marius,Gillenormand
55,39,Marius,Pontmercy
55,54,Marius,Lt.Gillenormand
55,26,Marius,Cosette
55,11,Marius,Valjean
55,16,Marius,Tholomyes
55,25,Marius,Thenardier
55,41,Marius,Eponine
55,48,Marius,Gavroche
56,49,BaronessT,Gillenormand
56,55,BaronessT,Marius
57,55,Mabeuf,Marius
57,41,Mabeuf,Eponine
57,48,Mabeuf,Gavroche
58,55,Enjolras,Marius
58,48,Enjolras,Gavroche
58,27,Enjolras,Javert
58,57,Enjolras,Mabeuf
58,11,Enjolras,Valjean
59,58,Combeferre,Enjolras
59,55,Combeferre,Marius
59,48,Combeferre,Gavroche
59,57,Combeferre,Mabeuf
60,48,Prouvaire,Gavroche
60,58,Prouvaire,Enjolras
60,59,Prouvaire,Combeferre
61,48,Feuilly,Gavroche
61,58,Feuilly,Enjolras
61,60,Feuilly,Prouvaire
61,59,Feuilly,Combeferre
61,57,Feuilly,Mabeuf
61,55,Feuilly,Marius
62,55,Courfeyrac,Marius
62,58,Courfeyrac,Enjolras
62,59,Courfeyrac,Combeferre
62,48,Courfeyrac,Gavroche
62,57,Courfeyrac,Mabeuf
62,41,Courfeyrac,Eponine
62,61,Courfeyrac,Feuilly
62,60,Courfeyrac,Prouvaire
63,59,Bahorel,Combeferre
63,48,Bahorel,Gavroche
63,62,Bahorel,Courfeyrac
63,57,Bahorel,Mabeuf
63,58,Bahorel,Enjolras
63,61,Bahorel,Feuilly
63,60,Bahorel,Prouvaire
63,55,Bahorel,Marius
64,55,Bossuet,Marius
64,62,Bossuet,Courfeyrac
64,48,Bossuet,Gavroche
64,63,Bossuet,Bahorel
64,58,Bossuet,Enjolras
64,61,Bossuet,Feuilly
64,60,Bossuet,Prouvaire
64,59,Bossuet,Combeferre
64,57,Bossuet,Mabeuf
64,11,Bossuet,Valjean
65,63,Joly,Bahorel
65,64,Joly,Bossuet
65,48,Joly,Gavroche
65,62,Joly,Courfeyrac
65,58,Joly,Enjolras
65,61,Joly,Feuilly
65,60,Joly,Prouvaire
65,59,Joly,Combeferre
65,57,Joly,Mabeuf
65,55,Joly,Marius
66,64,Grantaire,Bossuet
66,58,Grantaire,Enjolras
66,59,Grantaire,Combeferre
66,62,Grantaire,Courfeyrac
66,65,Grantaire,Joly
66,48,Grantaire,Gavroche
66,63,Grantaire,Bahorel
66,61,Grantaire,Feuilly
66,60,Grantaire,Prouvaire
67,57,MotherPlutarch,Mabeuf
68,25,Gueulemer,Thenardier
68,11,Gueulemer,Valjean
68,24,Gueulemer,Mme.Thenardier
68,27,Gueulemer,Javert
68,48,Gueulemer,Gavroche
68,41,Gueulemer,Eponine
69,25,Babet,Thenardier
69,68,Babet,Gueulemer
69,11,Babet,Valjean
69,24,Babet,Mme.Thenardier
69,27,Babet,Javert
69,48,Babet,Gavroche
69,41,Babet,Eponine
70,25,Claquesous,Thenardier
70,69,Claquesous,Babet
70,68,Claquesous,Gueulemer
70,11,Claquesous,Valjean
70,24,Claquesous,Mme.Thenardier
70,27,Claquesous,Javert
70,41,Claquesous,Eponine
70,58,Claquesous,Enjolras
71,27,Montparnasse,Javert
71,69,Montparnasse,Babet
71,68,Montparnasse,Gueulemer
71,70,Montparnasse,Claquesous
71,11,Montparnasse,Valjean
71,48,Montparnasse,Gavroche
71,41,Montparnasse,Eponine
71,25,Montparnasse,Thenardier
72,26,Toussaint,Cosette
72,27,Toussaint,Javert
72,11,Toussaint,Valjean
73,48,Child1,Gavroche
74,48,Child2,Gavroche
74,73,Child2,Child1
75,69,Brujon,Babet
75,68,Brujon,Gueulemer
75,25,Brujon,Thenardier
75,48,Brujon,Gavroche
75,41,Brujon,Eponine
75,70,Brujon,Claquesous
75,71,Brujon,Montparnasse
76,64,Mme.Hucheloup,Bossuet
76,65,Mme.Hucheloup,Joly
76,66,Mme.Hucheloup,Grantaire
76,63,Mme.Hucheloup,Bahorel
76,62,Mme.Hucheloup,Courfeyrac
76,48,Mme.Hucheloup,Gavroche
76,58,Mme.Hucheloup,Enjolras
<div id="canvas-svg"></div>
/*--- IMPORTANT GUIDELINES ---
1. Use div #canvas-svg for svg rendering
var svg = d3.select("#canvas-svg");
2. 'data' variable contains JSON data from Data tab
Do NOT overwrite this variable
3. To define customizable properties, use capitalized variable names,
and define them in Properties tab ---*/
var WIDTH = config.width, HEIGHT = config.height;
var nodes = {};
// Compute the distinct nodes from the links.
data.forEach(function(link) {
var sourceNode = nodes[link[config.source]] ||
(nodes[link[config.source]] = {name: link[config.source]});
link.source = sourceNode;
var targetNode = nodes[link[config.target]] ||
(nodes[link[config.target]] = {name: link[config.target]});
link.target = targetNode;
if (config.value) {
link.value = +link[config.value];
}
});
var width = WIDTH,
height = HEIGHT;
var force = d3.layout.force()
.nodes(d3.values(nodes))
.links(data)
.size([width, height])
.linkDistance(config.linkDistance)
.gravity(0.3)
.charge(config.charge)
.start();
var svg = d3.select("#canvas-svg").append("svg")
.attr("width", width)
.attr("height", height)
.call(d3.behavior.zoom().on("zoom", zoom))
.append("g");
// add the links and the arrows
var link = svg.selectAll(".link")
.data(force.links())
.enter().append("line")
.attr("class", "link")
.style("stroke", config.linkColor)
.style("stroke-width", function(d) { return 2; });
// define the nodes
var node = svg.selectAll(".node")
.data(force.nodes())
.enter().append("g")
.attr("class", "node")
.call(force.drag);
// add the nodes
node.append("circle")
.attr("class", "force-circle")
.style("fill", config.nodeColor)
.attr("r", 5);
if (config.showNodeLabel) {
// add the text
node.append("text")
.attr("class", "force-text")
.attr("x", 12)
.attr("dy", ".35em")
.style("font-size", "14px")
.text(function(d) { return d.name; });
}
var scaleX = 1, scaleY = 1, scale = 1, translateX = 0, translateY = 0;
function zoom() {
force.stop();
svg.attr("transform",
"translate(" + (d3.event.translate[0] + translateX) + "," + (d3.event.translate[1] + translateY) + ")"
+ " scale(" + (d3.event.scale - (1 - scale)) + ")");
}
function draw() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"; });
}
function scaleAndDraw() {
var xExtent = d3.extent(d3.values(nodes), function(n) { return n.x; }),
yExtent = d3.extent(d3.values(nodes), function(n) { return n.y; });
if ((xExtent[1] - xExtent[0]) > config.width) {
scaleX = (xExtent[1] - xExtent[0]) / config.width;
scaleY = (yExtent[1] - yExtent[0]) / config.height;
scale = 1 / Math.max(scaleX, scaleY);
translateX = Math.abs(xExtent[0]) * scale;
translateY = Math.abs(yExtent[0]) * scale,
svg.attr("transform", "translate(" +
translateX + "," + translateY + ")" +
" scale(" + scale + ")");
}
draw();
}
// add the curvy lines
force.on("tick", function() {
scaleAndDraw();
});
[
{
"label": "hello",
"value": 0
},
{
"label": "world",
"value": 1
}
]
var gulp = require('gulp'),
sass = require('gulp-sass'),
jade = require('gulp-jade'),
webserver = require('gulp-webserver')
// --- Basic Tasks ---
gulp.task('sass', function () {
gulp.src('sass/**/*.sass')
.pipe(sass({outputStyle: 'expanded'}).on('error', sass.logError))
.pipe(gulp.dest('./'));
});
gulp.task('templates', function() {
gulp.src(['templates/**/*.jade','!templates/**/_*.jade'])
.pipe(jade({pretty: true}))
.pipe(gulp.dest('./'))
});
gulp.task('watch', function () {
gulp.watch('sass/*.sass',['sass']);
gulp.watch('templates/*.jade',['templates']);
});
gulp.task('webserver', function() {
gulp.src('.')
.pipe(webserver({
livereload: true,
directoryListing: false,
open: true,
fallback: 'index.html'
}));
});
// Default Task
gulp.task('default', ['sass','templates','watch', 'webserver']);
{
"data": ["document.csv"],
"javascript": ["document.js"],
"stylesheet": ["document.css"],
"html": ["document.html"],
"externalLibraries": [
],
"properties": [{"label":"Source","name":"source","value":"sourceLabel","type":"data_column"},{"label":"Target","name":"target","value":"targetLabel","type":"data_column"},{"label":"Charge","name":"charge","value":-1000,"type":"number"},{"label":"Link Distance","name":"linkDistance","value":50,"type":"number"},{"label":"Node Color","name":"nodeColor","value":"#0f608b","type":"color"},{"label":"Link Color","name":"linkColor","value":"#ccc","type":"color"},{"label":"Show Node Label","name":"showNodeLabel","value":true,"type":"boolean"},{"label":"Width","name":"width","value":600,"type":"number"},{"label":"Height","name":"height","value":500,"type":"number"},{"label":"Value","name":"value","value":"sourceLabel","type":"data_column"}]
}
{
"name": "enterprise_workmap",
"version": "0.0.1",
"dependencies": {
},
"devDependencies": {
"gulp": "~3.9.0",
"gulp-sass": "~2.1.0",
"gulp-jade": "~1.1.0",
"gulp-connect": "~2.2.0",
"gulp-webserver": "~0.9.1"
}
}
#canvas {
width: 800px;
height: 600px;
}
#canvas-svg {
width: 800px;
height: 600px;
}
$(document).ready(function() {
// read manifest
$.get('manifest.json', function(manifest) {
window.config = {};
var properties = manifest.properties;
properties.forEach(function(p) {
if (p.type === "list") {
window.config[p.name] = p.value.split(/[,\n]/);
} else {
window.config[p.name] = p.value;
}
});
function loadDoc() {
// load HTML and append to body canvas
var document_html = manifest.html[0],
document_css = manifest.stylesheet[0]
$.get(document_html, function(html) {
$('#canvas').append(html);
function run() {
// load CSS
var css = $('<link rel="stylesheet" type="text/css" href="' + document_css + '" />');
$('body').append(css);
// load Javascript
for (var i = 0; i < manifest.javascript.length; i++) {
var js = manifest.javascript[i];
var script = $('<script type="text/javascript" src="' + js +'"></script>');
$('body').append(script);
}
}
function loadData(i) {
if (i < manifest.data.length) {
var document_data = manifest.data[i]
if (document_data.indexOf('.json') !== -1) {
$.get(document_data, function(data) {
window.data[document_data] = data;
loadData(i+1);
})
} else if (document_data.indexOf('.csv') !== -1) {
d3.csv(document_data, function(data) {
window.data[document_data] = data;
loadData(i+1);
});
} else if (document_data.indexOf('.tsv') !== -1) {
d3.tsv(document_data, function(data) {
window.data[document_data] = data;
loadData(i+1);
});
}
} else {
if (Object.keys(window.data).length === 1) {
window.data = window.data[Object.keys(window.data)[0]];
}
run();
}
}
window.data = {};
loadData(0);
});
}
if (manifest.externalLibraries && manifest.externalLibraries.length > 0) {
function loadExtLib(index) {
if (index < manifest.externalLibraries.length) {
var lib = manifest.externalLibraries[index];
if (lib.indexOf('.js') !== -1) {
$.getScript(lib, function() {
index++;
loadExtLib(index);
});
} else if (lib.indexOf('.css') !== -1) {
var css = $('<link rel="stylesheet" type="text/css" href="' + lib + '" />');
$('body').append(css);
index++;
loadExtLib(index);
}
} else {
loadDoc();
}
}
loadExtLib(0);
} else {
loadDoc();
}
});
});