highlightSeries plugin for jquery flot charts - javascript

I'm looking for help with the highlightSeries plugin made by Brian Peiris (http://brian.peiris.name/highlightSeries/). It doesn't appear to be working; I'm positive that the event is firing, because an alert test I performed earlier worked just fine, printing out $(this).text(). I'm trying to get the series on the chart to be highlighted when the user mouses over the series name in the legend (something which works perfectly fine on Mr. Peiris's website).
$('.server-chart').each(function() {
var serv = $(this).attr('id').substr(6);
var plotData = [];
//alert(serv + ": " + $.toJSON(serverStats[serv]));
for (var k in serverStats[serv].StatsByCollection) {
var outlabel = k;
var outdata = serverStats[serv].StatsByCollection[k];
plotData.push({ label: outlabel, data: outdata});
}
plotOptions = {
legend: {
container: $('#legend-' + serv),
labelFormatter: function(label, series) {
return '' + label + '';
},
noColumns: 2
},
series: {
lines: {
show: true,
fill: false
},
points: {
show: false,
fill: false
}
},
colors: colors,
grid: {
hoverable: false
},
highlightSeries: {
color: "#FF00FF"
}
}
$_plot = $.plot(this, plotData, plotOptions);
$plots.push($_plot);
$('#legend-' + serv + ' .legendLabel, #legend-' + serv + ' .legendColorBox').on('mouseenter', function () {
$_plot.highlightSeries($(this).text());
});
$('#legend-' + serv + ' .legendLabel, #legend-' + serv + ' .legendColorBox').on('mouseleave', function () {
$_plot.unHighlightSeries($(this).text());
});
});
I'm not sure what other code to put on here, so tell me if you need more; the charts are all working fine, this is just the part of the ready function setting up all of the plots and their options inside the placeholders.
Also, there's a couple of classes attached to the labels that are extraneous; I was trying different things to get this stuff to work.

The plugin requires a patched version of flot to work (it introduces a public drawSeries method). The last patched version is for an older version of flot (0.7).
With that said, I wouldn't use this plugin. If you just want to highlight a series on legend mouseover it's pretty simple.
$('#legend .legendLabel, #legend .legendColorBox').on('mouseenter', function() {
var label = $(this).text();
var allSeries = $_plot.getData();
// find your series by label
for (var i = 0; i < allSeries.length; i++){
if (allSeries[i].label == label){
allSeries[i].oldColor = allSeries[i].color;
allSeries[i].color = 'black'; // highlight it in some color
break;
}
}
$_plot.draw(); // draw it
});
$('#legend .legendLabel, #legend .legendColorBox').on('mouseleave', function() {
var label = $(this).text();
var allSeries = $_plot.getData();
for (var i = 0; i < allSeries.length; i++){
if (allSeries[i].label == label){
allSeries[i].color = allSeries[i].oldColor;
break;
}
}
$_plot.draw();
});
See example here.

Related

Can i use crosshairs with OHLC/candlestick charts using ChartJS

I have installed the crosshair plugin and am using chartJS 3.0 to take advantage of the candlestick charts but the crosshair does not appear. are these things compatible together? my data appear no problem but the crosshair never appears. how do i use these two things together? are there any working examples?
the tags i am using
<script src="https://cdn.jsdelivr.net/npm/luxon#1.24.1"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.0.0-beta.9/dist/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon#0.2.1"></script>
<script src="https://dd7tel2830j4w.cloudfront.net/f1614793727236x392906938665549250/chartjs-chart-financial.js"></script>
<script scr="https://cdn.jsdelivr.net/npm/chartjs-plugin-crosshair"></script>
and the chart code which also works
var divID = "chartContainer" + properties.chartid
var chartID = "myChart" + properties.chartid
instance.canvas.append('<div id="' + divID + '"></div>')
document.getElementById(divID).innerHTML = ' ';
document.getElementById(divID).innerHTML = '<canvas id=' + chartID + ' width="' + properties.bubble.width() + '" height="' + properties.bubble.height() + '"></canvas>';
var ctx = document.getElementById(chartID).getContext('2d');
var chart = new Chart(ctx, {
type: 'candlestick',
data: {
datasets: [{
label: 'CHRT - Chart.js Corporation',
data: getData()
}]
},
options: {
scales: {
y: {
min: 0,
max: 500
}
},
tooltips: {
mode: "interpolate",
intersect: false
},
plugins: {
crosshair: {
line: {
color: '#F66', // crosshair line color
width: 3, // crosshair line width
dashPattern: [5, 5] // crosshair line dash pattern
},
sync: {
enabled: true, // enable trace line syncing with other charts
group: 1, // chart group
suppressTooltips: false // suppress tooltips when showing a synced tracer
},
zoom: {
enabled: true, // enable zooming
zoomboxBackgroundColor: 'rgba(66,133,244,0.2)', // background color of zoom box
zoomboxBorderColor: '#48F', // border color of zoom box
zoomButtonText: 'Reset Zoom', // reset zoom button text
zoomButtonClass: 'reset-zoom', // reset zoom button class
},
callbacks: {
beforeZoom: function(start, end) { // called before zoom, return false to prevent zoom
return true;
},
afterZoom: function(start, end) { // called after zoom
}
}
}
}
}
});
function getData() {
var dates = properties.time.get(0, properties.time.length())
var opens = properties.open.get(0, properties.open.length())
var highs = properties.high.get(0, properties.high.length())
var lows = properties.low.get(0, properties.low.length())
var closes = properties.close.get(0, properties.close.length())
let data = []
for (i = 0; i < dates.length; i++) {
data.push({
t: dates[i].valueOf(),
o: opens[i],
h: highs[i],
l: lows[i],
c: closes[i]
})
}
console.log(data)
return data
}
chart.update()
The crosair plugin is not yet compatible with the new beta of version 3. They have a pr to be up to date with beta 11 but after that there have been breaking changes again. So you will have to update the plugin yourself or wait till it has been updated to support v3

Highcharts sparklines from ajax-inserted data

You have a html table and you want to show sparkline charts from your data, exactly as in this example (from highcharts demos):
https://codepen.io/_dario/pen/rNBOGVR
Highcharts suggested code follows:
/**
* Create a constructor for sparklines that takes some sensible defaults and merges in the individual
* chart options. This function is also available from the jQuery plugin as $(element).highcharts('SparkLine').
*/
Highcharts.SparkLine = function(a, b, c) {
var hasRenderToArg = typeof a === 'string' || a.nodeName,
options = arguments[hasRenderToArg ? 1 : 0],
defaultOptions = {
chart: {
renderTo: (options.chart && options.chart.renderTo) || this,
backgroundColor: null,
borderWidth: 0,
type: 'area',
margin: [2, 0, 2, 0],
width: 120,
height: 20,
style: {
overflow: 'visible'
},
// small optimalization, saves 1-2 ms each sparkline
skipClone: true
},
title: {
text: ''
},
credits: {
enabled: false
},
xAxis: {
labels: {
enabled: false
},
title: {
text: null
},
startOnTick: false,
endOnTick: false,
tickPositions: []
},
yAxis: {
endOnTick: false,
startOnTick: false,
labels: {
enabled: false
},
title: {
text: null
},
tickPositions: [0]
},
legend: {
enabled: false
},
tooltip: {
hideDelay: 0,
outside: true,
shared: true
},
plotOptions: {
series: {
animation: false,
lineWidth: 1,
shadow: false,
states: {
hover: {
lineWidth: 1
}
},
marker: {
radius: 1,
states: {
hover: {
radius: 2
}
}
},
fillOpacity: 0.25
},
column: {
negativeColor: '#910000',
borderColor: 'silver'
}
}
};
options = Highcharts.merge(defaultOptions, options);
return hasRenderToArg ?
new Highcharts.Chart(a, options, c) :
new Highcharts.Chart(options, b);
};
var start = +new Date(),
$tds = $('td[data-sparkline]'),
fullLen = $tds.length,
n = 0;
// Creating 153 sparkline charts is quite fast in modern browsers, but IE8 and mobile
// can take some seconds, so we split the input into chunks and apply them in timeouts
// in order avoid locking up the browser process and allow interaction.
function doChunk() {
var time = +new Date(),
i,
len = $tds.length,
$td,
stringdata,
arr,
data,
chart;
for (i = 0; i < len; i += 1) {
$td = $($tds[i]);
stringdata = $td.data('sparkline');
arr = stringdata.split('; ');
data = $.map(arr[0].split(', '), parseFloat);
chart = {};
if (arr[1]) {
chart.type = arr[1];
}
$td.highcharts('SparkLine', {
series: [{
data: data,
pointStart: 1
}],
tooltip: {
headerFormat: '<span style="font-size: 10px">' + $td.parent().find('th').html() + ', Q{point.x}:</span><br/>',
pointFormat: '<b>{point.y}.000</b> USD'
},
chart: chart
});
n += 1;
// If the process takes too much time, run a timeout to allow interaction with the browser
if (new Date() - time > 500) {
$tds.splice(0, i + 1);
setTimeout(doChunk, 0);
break;
}
// Print a feedback on the performance
if (n === fullLen) {
$('#result').html('Generated ' + fullLen + ' sparklines in ' + (new Date() - start) + ' ms');
}
}
}
doChunk();
However, in my use case, the data in the table (and the data-sparkline attribute) are not hard-coded like in the example, but loaded and displayed via an AJAX call, similar to below.
//here a table row gets compiled
var tableRow = '<tr id="row_' + word.id + '">';
//this is where the sparkline data go
tableRow += '<td class="has-sparkline"></td></tr>';
//the row gets appended to tbody
$('#wordstable tbody').append(tableRow);
//finally the sparkline data are attached
//data are a simple string such as "1,2,3,4,5"
var rowId = '#row_'+word.id;
var rowIdTd = rowId + ' td.has-sparkline';
$(rowIdTd).data('sparkline',word.sparkline);
This breaks the example logic and I can't have Highcharts "see" the data.
No particular error is returned (as the data, as far as Highcharts is concerned, just isn't there, so there's nothing to do).
The doChunk bit just does all the processing in advance, and when you add your row it is no longer processing. One way of dealing with this is pulling out the part that creates a single chart into a separate function (makeChart) and when you are doing your processing you use that part directly to create your sparkline.
For example, doChunk with split out makeChart:
function makeChart(td) {
$td = td;
stringdata = $td.data('sparkline');
arr = stringdata.split('; ');
data = $.map(arr[0].split(', '), parseFloat);
chart = {};
if (arr[1]) {
chart.type = arr[1];
}
$td.highcharts('SparkLine', {
series: [{
data: data,
pointStart: 1
}],
tooltip: {
headerFormat: '<span style="font-size: 10px">' + $td.parent().find('th').html() + ', Q{point.x}:</span><br/>',
pointFormat: '<b>{point.y}.000</b> USD'
},
chart: chart
});
}
// Creating 153 sparkline charts is quite fast in modern browsers, but IE8 and mobile
// can take some seconds, so we split the input into chunks and apply them in timeouts
// in order avoid locking up the browser process and allow interaction.
function doChunk() {
var time = +new Date(),
i,
len = $tds.length,
$td,
stringdata,
arr,
data,
chart;
for (i = 0; i < len; i += 1) {
makeChart($($tds[i]));
n += 1;
// If the process takes too much time, run a timeout to allow interaction with the browser
if (new Date() - time > 500) {
$tds.splice(0, i + 1);
setTimeout(doChunk, 0);
break;
}
// Print a feedback on the performance
if (n === fullLen) {
$('#result').html('Generated ' + fullLen + ' sparklines in ' + (new Date() - start) + ' ms');
}
}
}
And then a basic example of your ajax-code:
function ajaxIsh() {
var word = {
name: 'Bird', // is the word
id: 'bird',
sparkline: '1, 2, 3, 4, 5'
};
//here a table row gets compiled
var tableRow = '<tr id="row_' + word.id + '">';
//this is where the sparkline data go
tableRow += '<th>'+word.name+'</th><td class="has-sparkline"></td></tr>';
//the row gets appended to tbody
$('#table-sparkline tbody').append(tableRow);
//finally the sparkline data are attached
//data are a simple string such as "1,2,3,4,5"
var rowId = '#row_'+word.id;
var rowIdTd = rowId + ' td.has-sparkline';
$(rowIdTd).data('sparkline',word.sparkline);
makeChart($(rowIdTd));
}
See this JSFiddle demonstration of it in action.

Changing Tables in Highcharts Missing Row

I have an HTML table with some data, from that table I'm creating a chart:
var chart = Highcharts.chart('graph_user_1', {
data: {
table: 'table_user_1',
startColumn: 0,
endColumn: 1
},
chart: {
type: 'column'
},
title: {
text: 'Coverage'
},
yAxis: {
allowDecimals: true,
title: {
text: 'Hours'
}
},
tooltip: {
formatter: function() {
return '<b>' + this.series.name + '</b><br/>' +
this.point.y + ' Points - ' + this.point.name.toLowerCase();
}
},
plotOptions: {
column: {
colorByPoint: true
}
},
series: [{
id: 'series1'
}],
colors: [
'#ff0000',
'#00ff00',
'#0000ff',
'#3A8BEE',
'#F9B342',
'#DC4008'
]
});
I also have a filter, it lets me select some dates and filter the table, these rows of data that are not hidden, are appended to a hidden table on the page:
$("#to_date").on("change", function() {
var from = parseDate($('#from_date').val());
var to = parseDate($('#to_date').val());
var loop_count = 0;
var hidden_count = 0;
$("#body tr").each(function() {
var row = $(this);
var date_from = parseDate(row.find("td").eq(7).text());
var date_to = parseDate(row.find("td").eq(8).text());
var show = true;
show = isContained(date_from, date_to, from, to);
if (show) {
row.show();
legendArray.push(row); //pushes row to array
} else {
row.hide();
hidden_count++;
}
loop_count++;
});
if (hidden_count === loop_count) {
warning.prop("hidden", false);
warning.append("<strong>No results.</strong>");
}
restore(legendArray, chart);
});
The restore function at the end gets the array with rows and a chart reference, it appends the rows from the array to the new table, then changes the source of the data from the original to the hidden table (id="aux") and redraws it.
function restore(array) {
var table = document.getElementById('auxBody');
for (var i = 0; i <= array.length - 1; i++) {
table.appendChild(array[i][0].cloneNode(true));
}
var complete = function(options) {
var chart = $('#graph_user_1').highcharts();
var series1 = chart.get('series1');
series1.setData(options.series[0].data, false);
chart.redraw();
};
Highcharts.data({
table: 'aux',
complete: complete
});
}
After this, the graph IS updated, but it's always missing one row, the last one. I've printed the array, the new table, the nodes that are being appended, inspected, etc. All of this show the table with all the rows, but the graph is always missing the last one, I thought it was an index problem in the loop that adds the nodes but that doesn't seems to be the case.
As I posted earlier, it was a header issue with the table.
At creation I was appending the outerHTML of the copied table head:
newTable.append(newTHead[0].outerHTML);
Of course this caused an issue and the table had no headers, (even though it still showed on inspect) solution was removing the outerHTML and just appending the node, just a dumb conceptual mistake.
newTable.append(newTHead[0]);

Showing Progress while Child row loads

Coming again with another question :)
This time I had a requirement to show some progress while Child rows are being loaded. Since there is an Api call which relatively takes little time to return data, I do want to show the some progress unless the user who clicks the parent row is totally unaware whether there is a call done to see its child rows.
What I have done:
I wrote a style sheet class which has a
loader-small.gif
image as this:
tr.loading td.details-control {
background: url('/Images/loader-small.gif') no-repeat center center;
}
and applied like this:
$('#accountManagerEarningsDataTable tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var row = table.row(tr);
try {
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
//Calling the loading Class ------>
tr.addClass('loading');
// Open this row
var arrForTable1 = [];
var arrForTable2 = [];
totalBrokerage = 0;
totalRetailBrokerage = 0;
totalSelfServiceBrokerage = 0;
console.log('You selected: ' + row.data().AccountManagerID);
var settings = {
"columnDefs": [
{ targets: 1, align: "right", decimals: 0 },
{ targets: 2, align: "right", decimals: 0 },
{ targets: 3, align: "right", decimals: 0 },
{ targets: 4, align: "right", decimals: 2 },
{ targets: 5, align: "right", decimals: 2 }
]
};
//problems with asynchoronus call back
var response = organization_GetAccountManagerDetailEarningsAccountData(row.data(), purl2, pcontext);
if (response.success === "true") {
for (var i = 0; i < response.value.length; i++) {
for (var j = 0; j < response.value[i].Securities.length; j++) {
var itemRow2 = {};
itemRow2["Security ID"] = response.value[i].Securities[j].SecurityId;
itemRow2["Trades"] = response.value[i].Securities[j].Trades;
itemRow2["Buy Qty"] = response.value[i].Securities[j].BuyQuantity;
itemRow2["Sell Qty"] = response.value[i].Securities[j].SellQuantity;
itemRow2["Total Brkg"] = response.value[i].Securities[j].Effective_Brokerage;
itemRow2["Online Brkg"] = response.value[i].Securities[j].Online_Brokerage;
arrForTable2.push(itemRow2);
totalBrokerage = totalBrokerage + parseFloat(response.value[i].Securities[j].Effective_Brokerage);
totalSelfServiceBrokerage = totalSelfServiceBrokerage + parseFloat(response.value[i].Securities[j].Online_Brokerage);
}
totalBrokerage = Math.round(totalBrokerage * 100) / 100;
totalSelfServiceBrokerage = Math.round(totalSelfServiceBrokerage * 100) / 100;
totalRetailBrokerage = Math.round(totalRetailBrokerage * 100) / 100;
var itemRow1 = {};
itemRow1["Account ID"] = response.value[i].AccountId;
itemRow1["Account Name"] = response.value[i].AccountName;
itemRow1["..."] = '<div class="alert alert-info" role="alert">' + buildHtmlTable(arrForTable2, 'table2x' + j, settings) + '<p>Total Brokerage ' + numberWithCommas(totalBrokerage) + '</p></div>';
arrForTable1.push(itemRow1);
arrForTable2 = [];
totalBrokerage = 0;
totalRetailBrokerage = 0;
totalSelfServiceBrokerage = 0;
}
tr.removeClass('loading');
htmlTable1 = buildHtmlTable(arrForTable1, 'table1x' + i);
row.child(htmlTable1).show();
tr.addClass('shown');
}
else {
row.child('<table><tr><td>' + response.value[0].AccountId + '</td></tr></table>').show();
tr.addClass('shown');
};
}
} catch (e) {
console.log(e.message);
}
});
The Problem:
Firefox nicely shows the Progress image after the user clicks it, but Edge and Chrome does not show. Both browsers crossed this piece of code when I was debugging from developer tools of the respective browser.
Its browser compatible problem? Is there a solution for it? Help me please.
In case of chrome there is such an issue while showing the loading bar while making a server call. Please make the following changes where you are making the service call. First add the class loading to the table
tr.addClass('loading');
After that make the service call by giving a timeout function
setTimeout(function(){
var response = organization_GetAccountManagerDetailEarningsAccountData(row.data(), purl2, pcontext);
......
//Your service calls and response call backs
},1);
On providing a timeout (say 1ms), Chrome will get the time to bind the loading bar to DOM, In other case the DOM Object is not available to show the spinner.

On Hover function is not showing in Chrome for my Jvectormap

Can't figure out why only chrome will not function, it is working fine in IE and Firefox.
$(function () {
$('#jvectormap-mill').vectorMap({
map: 'world_mill_en',
backgroundColor: 'white',
regionStyle: {
initial: {
fill: '#002d62'
},
hover: {
fill: '#FEC057',
"fill-opacity": 1
}
},
series: {
regions: [{
scale: ['#00B5E6'],
attribute: 'fill',
values: SavillePartnerArray()
}]
},
onRegionLabelShow: function (e, label, code) {
for (var partner in SavillePartners) {
if (partner == code) {
$("#jvectormap-label").position = e.position;
return false;
}
}
},
onRegionOver: function (e, code) {
var label = $("#jvectormap-label");
var region = $(".jvectormap-region[data-code='" + code + "']");
for (var partner in SavillePartners) {
if (partner == code) {
var Title = SavillePartners[code].name;
// Create HTML
var stringHtml = '<div class="jvectormap-label2"><div id="titleTextbox"><span id="titleSpan">' + Title + '</span></div><div class="globeLogoDiv"><img src="/images/international-partner-logos/saville-globe.jpg" alt="globe"/></div><div class="savilleLogoDiv"><img src="/images/international-partner-logos/saville-logo.jpg" alt="savilleconsulting" class="savilleLogoImg"/></div>';
if (SavillePartners[code].accreditedTrainer == 1) {
stringHtml = stringHtml + '<div class="internationalPartnersContainer"><div class="internationalContainer"><strong>INTERNATIONAL</strong></div><div class="partnersContainer">PARTNER</div></div><div class="accreditedTrainerContainer" ><div class="accreditedContainer"><strong>ACCREDITED</strong></div><div class="trainerContainer">TRAINER</div></div>';
}
else {
stringHtml = stringHtml + '<div class="internationPartnersSingle"><strong>INTERNATIONAL PARTNER</strong></div>';
}
stringHtml = stringHtml + '</div>';
label.html(stringHtml);
label = region.mousemove(function (t) {
var label = $("#jvectormap-label");
label.css({
left: t.pageX + 15,
top: t.pageY + 15
});
});
// Expand the title text to fit
var spanWidth = $("#titleSpan").width();
var newFontSize = (250 / spanWidth * 12);
$("#titleSpan").css({ "font-size": newFontSize, "line-height": newFontSize / 1.2 + "px" });
return;
}
}
e.preventDefault();
},
onRegionOut: function (e, code) {
var label = $("#jvectormap-label");
label.html('');
label.display = 'none';
},
onRegionClick: function (e, code) {
for (var partner in SavillePartners) {
if (partner == code) {
var link = SavillePartners[code].link;
document.location.href = '/International/' + link;
}
}
},
focusOn: {
x: mapXFocus,
y: mapYFocus,
scale: mapScale
}
});
});
Developer tools are not showing anything to point me in the direction of why...
If you want to see for yourself how its working in FF and IE but not Chrome please click here and hover on the lighter blue Countries. Any help will be greatly appreciated as I have been stuck on this for hours.
I'm using Chrome Version 25.0.1364.172 and it is working for me. Which version are you using, is there more data? The color changes, what exactly are you trying to solve?

Categories

Resources