I'm using the morris.js chart along with the bootstrap slider.
What I want to do:
If the slider is moved, I want to insert an event-line into the chart at the position of the sliders value. Nothing special.
The problem:
The chart isn't redrawing after setting the event. When inserting new data, the chart will be redrawn automatically. So I tried refreshing (to check for correct syntax) by passing the existing data to the chart again like this:
chart.setData(chart.options.data);
This is working! The new event gets drawn into the chart. Unfortunately this has a bad performance as the chart is redrawing all the data.
The documentation says there is chart.redraw()
. It's just not working for me. Maybe someone of you can find out why.
Just run the snippet and switch the radio-buttons to test both methods and you'll see the problem.
// Chart creation - not interesting
var chart = new Morris.Line({
element: 'chart',
ymin: 0,
ymax: 100,
gridIntegers: true,
parseTime:false,
// Will be set below
data: [ ],
xkey: 'position',
ykeys: ['value'],
labels: ['Value'],
hideHover: "always",
pointSize: 0,
continuousLine: false,
goalStrokeWidth: 3,
axes: true,
grid: true,
numLines: 6,
eventLineColors: [ "red" ],
smooth: true
});
// Inserting some values
var values = [101]
for(i = 1; i <= 100; i += 1) {
var x = 100/(Math.pow((i-50), 2)+4);
values.push({ position: i, value: x });
}
chart.setData(values);
// Create slider
$('#slider').slider({
tooltip: 'never',
tooltip_position:'left',
height: 300,
length: 300,
});
// If the slider moves, I want to set its value as an event-line
$("#slider").on("slideStop", function(slideEvt) {
chart.options.events = [ slideEvt.value ];
// Check inserting-data VS chart.redraw()
// Both should work... chart.redraw() isnt.
if(document.getElementById('insert').checked)
chart.setData(chart.options.data);
else if(document.getElementById('redraw').checked)
chart.redraw();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script src="http://cdn.oesmith.co.uk/morris-0.5.1.min.js"></script>
<link href="http://cdn.oesmith.co.uk/morris-0.5.1.css" rel="stylesheet"/>
<!-- Bootstrap slider -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/bootstrap-slider.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/css/bootstrap-slider.min.css">
<div id="chart" style="height: 150px;width:500px;"></div>
<form action="">
<input checked="true" id="insert" type="radio" name="refreshMethod"> Insert (working)<br>
<input id="redraw" type="radio" name="refreshMethod"> Redraw (not working)<br>
</form>
<input id="slider" type="text" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="50"/>
I appreciate every help in here. Thank you very much!
Important edit:
As soon as I can set a bounty (+1 hour) I'll do so. A very important additional part of this question is how to bind the slider to the single chart-event without lagging around. Currently the performance is very low when using the slide
event instead of slideStop
.
It's not working because internally chart.events
is not being set when you call chart.redraw()
. This property is set inside setData
with the line this.events = this.options.events
.
To correct for this: In your code use chart.events = [val]
rather than chart.options.events = [val];
Personally, I'd set them both in case setData
is called again, but that's up to you.
So in your demo:
...
else if(document.getElementById('redraw').checked) {
chart.events = [ slideEvt.value ];
chart.redraw();
}
EDIT:
Added a chart.quickRedraw
function. This removes unnecessary recalculations from the redraw function (refer to the commented out code for what is now excluded):
chart.quickRedraw = function() {
this.raphael.clear();
//this._calc();
this.drawGrid();
//this.drawGoals();
this.drawEvents();
this.draw();
};
Demo has been updated with the third option.
// Chart creation - not interesting
var chart = new Morris.Line({
element: 'chart',
ymin: 0,
ymax: 100,
gridIntegers: true,
parseTime:false,
// Will be set below
data: [ ],
xkey: 'position',
ykeys: ['value'],
labels: ['Value'],
hideHover: "always",
pointSize: 0,
continuousLine: false,
goalStrokeWidth: 3,
axes: true,
grid: true,
numLines: 6,
eventLineColors: [ "red" ],
smooth: true
});
// Inserting some values
var values = [101]
for(i = 1; i <= 100; i += 1) {
var x = 100/(Math.pow((i-50), 2)+4);
values.push({ position: i, value: x });
}
chart.setData(values);
// Create slider
$('#slider').slider({
tooltip: 'never',
tooltip_position:'left',
height: 300,
length: 300,
});
// If the slider moves, I want to set its value as an event-line
$("#slider").on("slideStop", function(slideEvt) {
chart.options.events = [ slideEvt.value ];
// Check inserting-data VS chart.redraw()
// Both should work... chart.redraw() isnt.
if(document.getElementById('insert').checked)
chart.setData(chart.options.data);
else if(document.getElementById('redraw').checked) {
chart.events = [ slideEvt.value ];
chart.redraw();
} else if(document.getElementById('quickerRedraw').checked) {
chart.events = [ slideEvt.value ];
chart.quickRedraw();
}
});
chart.quickRedraw = function() {
this.raphael.clear();
//this._calc();
this.drawGrid();
//this.drawGoals();
this.drawEvents();
this.draw();
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script src="http://cdn.oesmith.co.uk/morris-0.5.1.min.js"></script>
<link href="http://cdn.oesmith.co.uk/morris-0.5.1.css" rel="stylesheet"/>
<!-- Bootstrap slider -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/bootstrap-slider.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/css/bootstrap-slider.min.css">
<div id="chart" style="height: 150px;width:500px;"></div>
<form action="">
<input checked="true" id="insert" type="radio" name="refreshMethod"> Insert (working)<br>
<input id="redraw" type="radio" name="refreshMethod"> Redraw (working)<br>
<input id="quickerRedraw" type="radio" name="refreshMethod"> Quicker Redraw<br>
</form>
<input id="slider" type="text" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="50"/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With