dcos-dygraphs
Version:
dygraphs is a fast, flexible open source JavaScript charting library.
339 lines (305 loc) • 11.2 kB
HTML
<html>
<head>
<title>Hairlines demo</title>
<script type="text/javascript" src="../dist/dygraph.js"></script>
<!-- Include the Javascript for the plug-in -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js"></script>
<link rel='stylesheet' href='http://code.jquery.com/ui/1.10.1/themes/base/jquery-ui.css' />
<script type="text/javascript" src="../src/extras/hairlines.js"></script>
<script type="text/javascript" src="../src/extras/super-annotations.js"></script>
<style>
#demodiv {
position: absolute;
left: 10px;
right: 200px;
height: 400px;
display: inline-block;
}
#status {
position: absolute;
right: 10px;
width: 180px;
height: 400px;
display: inline-block;
}
#controls {
position: absolute;
left: 10px;
margin-top: 420px;
}
/* This style & the next show how you can customize the appearance of the
hairlines */
.hairline-info {
border: 1px solid black;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
display: table; /* shrink to fit */
min-width: 100px;
z-index: 10; /* should appear on top of the chart */
padding: 3px;
background: white;
font-size: 14px;
cursor: move;
}
.dygraph-hairline {
/* border-right-style: dotted !important; */
cursor: move;
}
.dygraph-hairline.selected div {
left: 2px ;
width: 2px ;
}
.hairline-info.selected {
border: 2px solid black;
padding: 2px;
}
.annotation-info {
background: white;
border-width: 1px;
border-style: solid;
padding: 4px;
display: table; /* shrink to fit */
box-shadow: 0 0 4px gray;
cursor: move;
min-width: 120px; /* prevents squishing at the right edge of the chart */
}
.annotation-info.editable {
min-width: 180px; /* prevents squishing at the right edge of the chart */
}
.dygraph-annotation-line {
box-shadow: 0 0 4px gray;
}
</style>
</head>
<body>
<h2>Hairlines Demo</h2>
<p>Click the chart to add a hairline. Drag the hairline to move it.</p>
<p>Click a point to add an editable annotation. Drag it to move it up/down.</p>
<!--
The "info box" for each hairline is based on this template.
Customize it as you wish. The .hairline-legend element will be populated
with data about the current points and the .hairline-kill-button element
will remove the hairline when clicked. Everything else will be untouched.
-->
<div id="hairline-template" class="hairline-info" style="display:none">
<button class='hairline-kill-button'>Kill</button>
<div class='hairline-legend'></div>
</div>
<div id="annotation-template" class="annotation-info" style="display:none">
<div>{{text}}</div>
<div>{{x}}, {{series}}: {{y}}</div>
</div>
<div id="annotation-editable-template" class="annotation-info" style="display:none">
<button class='annotation-kill-button'>Delete</button>
<button class='annotation-update'>Change</button>
<button class='annotation-cancel'>Cancel</button><br/>
<input dg-ann-field='text' type='text' size=30 value='{{text}}' />
<div>{{x}}, {{series}}: {{y}}</div>
</div>
<script type="text/javascript">
$(document).on('keyup', '.annotation-info input', function(e) {
var $annotationDiv = $(this).parent('.annotation-info');
if (e.keyCode == 13 || e.keyCode == 10) { // enter
$annotationDiv.find('.annotation-update').click();
} else if (e.keyCode == 27) { // escape
$annotationDiv.find('.annotation-cancel').click();
}
})
.on('dblclick', '.annotation-info', function(e) {
if (e.target.tagName == 'INPUT') return;
$(this).find('.annotation-cancel').click();
});
</script>
<div id="demodiv"></div>
<div id="status"></div>
<div id="controls">
<input type="checkbox" id="update" checked=true><label for="update"> Update</label>
<button id="add-button">Add a Hairline</button>
<button id="remove-button">Remove a Hairline</button>
<button id="reset-button">Reset Hairlines</button>
<br/>
Hairline mode:
<input type=radio name="hairline-mode" id="hairline-interpolated" checked=true>
<label for="hairline-interpolated"> Interpolated</label>
<input type=radio name="hairline-mode" id="hairline-closest">
<label for="hairline-closest"> Closest</label>
<p>Learn more about the <a href="https://docs.google.com/document/d/1OHNE8BNNmMtFlRQ969DACIYIJ9VVJ7w3dSPRJDEeIew/edit">Hairlines/Super-annotations plugins and their APIs</a>.</p>
</div>
<script type="text/javascript">
var last_t = 0;
var data = [];
var fn = function(t) {
return Math.sin(Math.PI/180 * t * 4);
};
for (; last_t < 200; last_t++) {
data.push([last_t, fn(last_t)]);
}
hairlines = new Dygraph.Plugins.Hairlines({
divFiller: function(div, data) {
// This behavior is identical to what you'd get if you didn't set
// this option. It illustrates how to write a 'divFiller'.
var html = Dygraph.Plugins.Legend.generateLegendHTML(
data.dygraph, data.hairline.xval, data.points, 10);
$('.hairline-legend', div).html(html);
$(div).data({xval: data.hairline.xval}); // see .hover() below.
}
});
annotations = new Dygraph.Plugins.SuperAnnotations({
defaultAnnotationProperties: {
'text': 'Annotation Description'
}
});
g = new Dygraph(
document.getElementById("demodiv"),
data,
{
labelsDiv: document.getElementById('status'),
labelsSeparateLines: true,
legend: 'always',
labels: [ 'Time', 'Value' ],
axes: {
x: {
valueFormatter: function(val) {
return val.toFixed(2);
}
},
y: {
pixelsPerLabel: 50
}
},
// Set the plug-ins in the options.
plugins : [
annotations,
hairlines
]
}
);
var shouldUpdate = true;
var update = function() {
if (!shouldUpdate) return;
data.push([last_t, fn(last_t)]);
last_t++;
data.splice(0, 1);
g.updateOptions({file: data});
};
window.setInterval(update, 1000);
// Control handlers
$('#update').on('change', function() {
shouldUpdate = $(this).is(':checked');
});
$('#add-button').on('click', function(e) {
var h = hairlines.get();
h.push({xval: 137});
hairlines.set(h);
});
$('#remove-button').on('click', function(e) {
var h = hairlines.get();
if (h.length > 0) {
var idx = Math.floor(h.length / 2);
h.splice(idx, 1);
}
hairlines.set(h);
});
$('#reset-button').on('click', function(e) {
setDefaultState();
});
function setHairlineModeRadio() {
var hs = hairlines.get();
if (hs.length) {
var interpolated = hs[0].interpolated;
$('#hairline-interpolated').prop('checked', interpolated);
$('#hairline-closest').prop('checked', !interpolated);
}
}
$('[name=hairline-mode]').change(function() {
var interpolated = $('#hairline-interpolated').is(':checked');
var hs = hairlines.get();
for (var i = 0; i < hs.length; i++) {
hs[i].interpolated = interpolated;
}
hairlines.set(hs);
});
// Persistence
function loadFromStorage() {
hairlines.set(JSON.parse(localStorage.getItem('hairlines')));
annotations.set(JSON.parse(localStorage.getItem('annotations')));
setHairlineModeRadio();
}
$(hairlines).on('hairlinesChanged', function(e) {
localStorage.setItem('hairlines', JSON.stringify(hairlines.get()));
setHairlineModeRadio();
});
$(annotations).on('annotationsChanged', function(e) {
localStorage.setItem('annotations', JSON.stringify(annotations.get()));
});
function setDefaultState() {
// triggers 'hairlinesChanged' and 'annotationsChanged' events, above.
hairlines.set([{xval: 55}]);
annotations.set([{
xval: 67,
series: 'Value',
text: 'Bottom'
},
{
xval: 137,
series: 'Value',
text: 'Fast Change'
}]);
}
if (!localStorage.getItem('hairlines') ||
!localStorage.getItem('annotations')) {
setDefaultState();
} else {
loadFromStorage();
}
// Set focus on text box when you edit an annotation.
$(annotations).on('beganEditAnnotation', function(e, a) {
$('input[type=text]', a.infoDiv).focus();
});
// Select/Deselect hairlines on click.
$(document).on('click', '.hairline-info', function() {
console.log('click');
var xval = $(this).data('xval');
var hs = hairlines.get();
for (var i = 0; i < hs.length; i++) {
if (hs[i].xval == xval) {
hs[i].selected = !hs[i].selected;
}
}
hairlines.set(hs);
});
// Demonstration of how to use various other event listeners
$(hairlines).on({
'hairlineMoved': function(e, data) {
// console.log('hairline moved from', data.oldXVal, ' to ', data.newXVal);
},
'hairlineCreated': function(e, data) {
console.log('hairline created at ', data.xval);
},
'hairlineDeleted': function(e, data) {
console.log('hairline deleted at ', data.xval);
}
});
$(annotations).on({
'annotationCreated': function(e, data) {
console.log('annotation created at ', data.series, data.xval);
},
'annotationMoved': function(e, data) {
console.log('annotation moved from ', data.oldYFrac, ' to ', data.newYFrac);
},
'annotationDeleted': function(e, data) {
console.log('annotation deleted at ', data.series, data.xval);
},
'annotationEdited': function(e, data) {
console.log('edited annotation at ', data.series, data.xval);
},
'cancelEditAnnotation': function(e, data) {
console.log('edit canceled on annotation at ', data.series, data.xval);
}
});
// TODO(danvk): demonstrate other annotations API methods.
</script>
</body>
</html>