JSFiddle - React, Tailwind, and code Playground
HTML
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css">
<div id="sprintVelocityLine">
<span id="velocityLabel" class="css-vertical-text"></span>
</div>
<ul class="unstyled">
<li data-story-id="6428" class="level0" data-story-size="5" data-story-qa=""> <span>6428</span>
</li>
<li data-story-id="4267" class="level0" data-story-size="8" data-story-qa="Talk with Craig"> <span>4267</span>
<ul class="unstyled">
<li data-story-id="4196" data-dependencies="4267,Frommer" class="level1" data-story-size="13" data-story-qa="S"> <span>4196</span>
<ul class="unstyled">
<li data-story-id="4197" data-dependencies="4196,4267,Frommer" class="level2" data-story-size="8" data-story-qa="M"> <span>4197</span>
</li>
</ul>
</li>
<li data-story-id="4197" data-dependencies="4196,4267,Frommer" class="level2" data-story-size="8" data-story-qa="M"> <span>4197</span>
</li>
<li data-story-id="5075" data-dependencies="6088,4267" class="level1" data-story-size="5" data-story-qa="M"> <span>5075</span>
</li>
<li data-story-id="4268" data-dependencies="4267" class="level1" data-story-size="5" data-story-qa="Talk with Craig"> <span>4268</span>
</li>
<li data-story-id="4269" data-dependencies="4267" class="level1" data-story-size="5" data-story-qa="Talk with Craig"> <span>4269</span>
</li>
<li data-story-id="4270" data-dependencies="4267" class="level1" data-story-size="13" data-story-qa="Talk with Craig"> <span>4270</span>
</li>
</ul>
</li>
<li data-story-id="Frommer" class="non-story"> <span>Frommer</span>
<ul class="unstyled">
<li data-story-id="4196" data-dependencies="4267,Frommer" class="level1" data-story-size="13"...
CSS
#sprintVelocityLine
{
position: fixed;
width: 30px;
height: 100%; /* or height in PX */
opacity: 0.3;
background-color: #f89406;
}
.css-vertical-text {
display:block;
writing-mode:tb-rl;
margin-top:50px;
-webkit-transform:rotate(90deg);
-moz-transform:rotate(90deg);
-o-transform: rotate(90deg);
white-space:nowrap;
font-weight:bold;
font-size:24px;
color: #fff;
}
JavaScript
(function () {
var sprintVelocity = 15,
multiplier = 25,
padding = 35 + 14;
function getData(elem) {
var size = parseInt(elem.data("story-size")),
id = elem.data("story-id"),
dependencies = (elem.data("dependencies") + "").split(","),
qa = elem.data("story-qa");
if (isNaN(size)) {
size = 0;
}
return {
id: id,
size: size,
qa: qa,
dependencies: dependencies
};
}
function getDependenciesSize(elem) {
var data = getData(elem),
depSelector = $.map(data.dependencies, function (d) {
return "li[data-story-id=\"" + d + "\"]";
}).join(","),
largest = 0;
$(depSelector).each(function () {
var item = $(this),
data = getData(item),
curSize = data.size;
curSize += getDependenciesSize(item);
if (curSize > largest) {
largest = curSize;
}
});
return largest;
}
$("#sprintVelocityLine").css("left", sprintVelocity * multiplier + padding);
$("#velocityLabel").text("Sprint Velocity - " + sprintVelocity);
$("li").each(function (i) {
var item = $(this),
data = getData(item),
depSize = getDependenciesSize(item);
if (data.size > 0) {
item.css("width", (data.size + depSize) * multiplier);
item.prepend("<span class='pull-right'>(" + depSize + ") " + data.size + "</span>");
}
});
$(".level0").addClass("alert alert-success");
$(".level1").addClass("alert");
$(".level2").addClass("alert alert-error");
$(".non-story").addClass("alert alert-info");
}());