Using JavaScript for Version Controlled Goals With vis.js
I’ve tried different ways of writing down goals over the years.
Here’s a list of the things I’ve tried:
- A good old-fashioned handwritten list (which I quickly ditched in favor of more computer based solutions)
- A list in Evernote
- An Excel sheet
In all these methods, I’ve always been missing a visual way to look at how I’m doing on my goals over time.
A Goal Timeline
I read an interesting article on medium by someone who apparently started 6 companies about How To 3x Your Productivity in 10 Minutes a Week.
There’s a lot of the standard stuff about setting goals in specific areas of your life (family, career, etc.) but the most interesting thing was he used a timeline to showcase all of his goals with their respective end dates.
Enter vis.js and its timeline feature
Being a programmer, I wanted to be able to version control my goals. I figured there must be some JavaScript library that could help me do this. After hitting Google for a few minutes, I eventually stumbled across vis.js and its timeline library.
Step 1 – Construct a basic HTML template
I’m going to give you the skeleton code I used at the end of this post, so don’t worry if you’re not getting this all at once. First, setup a standard basic HTML template.
Step 2 – Link to the css and js libraries via a CDN
Next, I just linked to 2 files – one was the CSS and the other was the JavaScript library provided by vis.js.
Step 3 – Add the code you need by looking at the documentation
The timeline documentation is pretty good in my opinion. So it’s pretty easy to get started with a basic timeline.
Skeleton code sample
Below is the source code I used (it’s one giant HTML page) sanitized for privacy reasons. But you can see the different CSS styles I used to color the timeline bars differently.
<!DOCTYPE html>
<html>
<head>
<title>Timeline basic demo</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.16.1/vis.min.js"></script>
<link
href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.16.1/vis.min.css"
rel="stylesheet"
type="text/css"
/>
<style type="text/css">
body,
html {
font-family: sans-serif;
}
.vis-item.green {
background-color: greenyellow;
border-color: green;
}
.vis-item.firebrick {
background-color: firebrick;
border-color: darkred;
color: white;
}
.vis-item.orange {
background-color: orange;
border-color: darkorange;
}
.vis-item.crimson {
background-color: crimson;
border-color: purple;
}
.vis-item.blue {
background-color: darkturquoise;
border-color: blue;
}
.vis-item.gold {
background-color: gold;
border-color: blue;
}
.vis-item.mediumpurple {
background-color: mediumpurple;
border-color: blue;
color: white;
}
.vis-item.done {
background-color: limegreen;
border-color: black;
}
</style>
</head>
<body>
<div id="visualization"></div>
<script type="text/javascript">
//create goal data set with groups
var container = document.getElementById('visualization');
var groupNames = [
'Relationships',
'Financial',
'Career',
'Business',
'Fun',
'Spiritual',
'Health',
];
var groupStyles = [
'crimson',
'green',
'blue',
'mediumpurple',
'orange',
'gold',
'firebrick',
];
var groups = new vis.DataSet();
for (var g = 0; g < groupNames.length; g++) {
groups.add({id: g, content: groupNames[g]});
}
// create a dataset with items
var items = new vis.DataSet();
// date months are 0-based index
var start = new Date(2016, 0, 1);
var end = new Date(2016, 11, 31);
var group = 0;
var i = 0;
// relationships
items.add({
id: i++,
group: group,
content: 'Goal 1 (' + groupNames[group] + ')',
className: groupStyles[group++],
start: start,
end: end,
type: 'range',
});
// financial
items.add({
id: i++,
group: group,
content: 'Goal 2 (' + groupNames[group] + ')',
className: groupStyles[group],
start: start,
end: end,
type: 'range',
});
items.add({
id: i++,
group: group,
content: 'Goal 3 (' + groupNames[group] + ')',
className: groupStyles[group++],
start: start,
end: end,
type: 'range',
});
// career
items.add({
id: i++,
group: group,
content: 'Goal 4 (' + groupNames[group] + ')',
className: groupStyles[group],
start: start,
end: end,
type: 'range',
});
items.add({
id: i++,
group: group,
content: 'Goal 5 (' + groupNames[group] + ')',
className: groupStyles[group],
start: start,
end: end,
type: 'range',
});
items.add({
id: i++,
group: group,
content: 'Goal 6 (' + groupNames[group] + ')',
className: groupStyles[group],
start: start,
end: end,
type: 'range',
});
items.add({
id: i++,
group: group,
content: 'Goal 7 (' + groupNames[group] + ')',
className: groupStyles[group],
start: start,
end: end,
type: 'range',
});
items.add({
id: i++,
group: group,
content: 'Goal 8 (' + groupNames[group] + ')',
className: 'done',
start: start,
end: end,
type: 'range',
});
items.add({
id: i++,
group: group,
content: 'Goal 9 (' + groupNames[group] + ')',
className: groupStyles[group++],
start: start,
end: end,
type: 'range',
});
// business
items.add({
id: i++,
group: group,
content: 'Goal 10 (' + groupNames[group] + ')',
className: groupStyles[group],
start: start,
end: end,
type: 'range',
});
items.add({
id: i++,
group: group,
content: 'Goal 11 (' + groupNames[group] + ')',
className: groupStyles[group++],
start: start,
end: end,
type: 'range',
});
// fun
items.add({
id: i++,
group: group,
content: 'Goal 12 (' + groupNames[group] + ')',
className: groupStyles[group],
start: start,
end: end,
type: 'range',
});
items.add({
id: i++,
group: group,
content: 'Goal 13 (' + groupNames[group] + ')',
className: groupStyles[group++],
start: start,
end: end,
type: 'range',
});
// spiritual
items.add({
id: i++,
group: group,
content: 'Goal 14 (' + groupNames[group] + ')',
className: groupStyles[group++],
start: start,
end: end,
type: 'range',
});
// health
items.add({
id: i++,
group: group,
content: 'Goal 15 (' + groupNames[group] + ')',
className: groupStyles[group],
start: start,
end: end,
type: 'range',
});
items.add({
id: i++,
group: group,
content: 'Goal 16 (' + groupNames[group] + ')',
className: groupStyles[group++],
start: start,
end: end,
type: 'range',
});
// create visualization
var container = document.getElementById('visualization');
var options = {
groupOrder: 'content', // groupOrder can be a property name or a sorting function
};
var timeline = new vis.Timeline(container);
timeline.setOptions(options);
timeline.setGroups(groups);
timeline.setItems(items);
</script>
</body>
</html>