Tooltip position is not working properly in D3 Funnel Chart - javascript

I am trying to do a d3 horizontal funnel chart.
Everything is working properly but tooltip position is not working properly it appears at a different location.
Here is my code:
const data = [
["L0", 10],
["L1", 0],
["L2", 5],
["L3", 10],
["L4", 3],
["L5", 10]
];
newdata = data.map(function (d,i){
var new_d = d
if (new_d[1] == 0){
new_d[1] = 0.50
}
return new_d
})
const options = {
chart: {
width: 200,
height: 450,
bottomWidth: 1 / 2,
bottomPinch: 1,
},
block: {
dynamicSlope: true,
dynamicHeight: true,
minHeight:50
},
label: {
enabled: true,
fontSize: '18px',
fill: '#fff',
/* format: '{l}: {f}' */
format: function(label, value) {
console.log('value', value);
if(value ==0.50){
var a=0;
return label+ ":" + a;
}else{
return label+ ":" + value;
}
}
},
tooltip: {
enabled: true,
format: '{l}: {f}'
}
};
const chart = new D3Funnel('#funnel');
chart.draw(newdata, options);
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://rawgit.com/jakezatecky/d3-funnel/master/dist/d3-funnel.min.js"></script>
<div id="funnel" style="transform: rotate(270deg);height: 539px;width:1px;margin-left:267px;"></div>
(from http://jsfiddle.net/3x265bLj/79/)

Related

Click on chartjs pie slice to hide the slice

I'm trying to get chartjs to hide pie slices on click; the same behavior seen when clicking on the legend.
Here is the code I'm using - I commented out the code that actually removes the data from the chart since it doesn't re-render the pie chart correctly.
const values = [50, 55, 60, 33];
const data = {
labels: ["India", "China", "US", "Canada"],
datasets: [{
data: values,
backgroundColor: [
"#4b77a9",
"#5f255f",
"#d21243",
"#B27200"
],
borderColor: "#fff"
}]
};
const options = {
tooltips: {
enabled: false
},
legend: {
enabled: true,
position: 'bottom'
},
animation: false,
onClick: handleClick,
plugins: {
datalabels: {
formatter: (value = 0, ctxx) => {
const sum = values.reduce((acc, val = 0) => (acc + val), 0);
return `${(value * 100 / sum).toFixed(2)}%`;
},
color: '#fff',
}
}
};
const ctx = document.getElementById("pie-chart").getContext('2d');
const myChart = new Chart(ctx, {
type: 'pie',
data,
options: options
});
function handleClick(e, slice) {
setTimeout(() => {
const legend = myChart.legend.legendItems;
if (slice && slice[0]) {
// get clicked on slice index
const sliceIndex = slice[0]._index;
// Removing the data "really" messes up the chart
// myChart.data.labels.splice(sliceIndex, 1);
// myChart.data.datasets[0].data.splice(sliceIndex, 1);
legend[sliceIndex].hidden = true;
chart.update();
}
const visibleSlices = legend.filter(l => !l.hidden);
console.log('visible slices', visibleSlices);
});
}
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#0.4.0/dist/chartjs-plugin-datalabels.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="pie-chart"></canvas>
It seems like setting the hidden flag then updating the chart should work because that's what the plugin is doing: https://github.com/chartjs/Chart.js/blob/master/src/plugins/plugin.legend.js#L20-L30.
The code below is hiding a slice by the index
myChart.getDatasetMeta(0).data[sliceIndex].hidden = true
const values = [50, 55, 60, 33];
const data = {
labels: ["India", "China", "US", "Canada"],
datasets: [{
data: values,
backgroundColor: [
"#4b77a9",
"#5f255f",
"#d21243",
"#B27200"
],
borderColor: "#fff"
}]
};
const options = {
tooltips: {
enabled: false
},
legend: {
enabled: true,
position: 'bottom'
},
animation: false,
onClick: handleClick,
plugins: {
datalabels: {
formatter: (value = 0, ctxx) => {
const sum = values.reduce((acc, val = 0) => (acc + val), 0);
return `${(value * 100 / sum).toFixed(2)}%`;
},
color: '#fff',
}
}
};
const ctx = document.getElementById("pie-chart").getContext('2d');
const myChart = new Chart(ctx, {
type: 'pie',
data,
options: options
});
function handleClick(e, slice) {
setTimeout(() => {
const legend = myChart.legend.legendItems;
if (slice && slice[0]) {
const sliceIndex = slice[0]._index;
myChart.getDatasetMeta(0).data[sliceIndex].hidden = true
myChart.update();
}
});
}
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#0.4.0/dist/chartjs-plugin-datalabels.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="pie-chart"></canvas>

How to show more than one "dataMax" in Highcharts?

Currently, I'm showing a max point in the line chart. But I want to change dataMax to top 5 max value points in chart.How can I achieve this in Highcharts?
var defaultData = 'urlto.csv';
var urlInput = document.getElementById('fetchURL');
var pollingCheckbox = document.getElementById('enablePolling');
var pollingInput = document.getElementById('pollingTime');
function createChart() {
Highcharts.chart('closed5', {
chart: {
type: 'area',
zoomType: 'x'
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
style: {},
formatter: function() {
if (this.y === this.series.dataMax) {
return this.y;
}
}
}
}
},
title: {
text: 'Chart for charting'
},
data: {
csvURL: urlInput.value,
enablePolling: pollingCheckbox.checked === true,
dataRefreshRate: parseInt(pollingInput.value, 10)
}
});
if (pollingInput.value < 1 || !pollingInput.value) {
pollingInput.value = 1;
}
}
urlInput.value = defaultData;
// We recreate instead of using chart update to make sure the loaded CSV
// and such is completely gone.
pollingCheckbox.onchange = urlInput.onchange = pollingInput.onchange = createChart;
// Create the chart
createChart();
As #ewolden rightly noticed, you can sort your data and show only the five highest values:
var data = [11, 22, 33, 44, 55, 66, 15, 25, 35, 45, 55, 65],
sortedData = data.slice().sort(function(a, b){
return b - a
});
Highcharts.chart('container', {
series: [{
data: data,
dataLabels: {
enabled: true,
formatter: function() {
if (sortedData.indexOf(this.y) < 5) {
return this.y;
}
}
}
}]
});
Live demo: http://jsfiddle.net/BlackLabel/xkf2w5tb/
API: https://api.highcharts.com/highmaps/series.mapbubble.dataLabels.formatter
As far as I know formatter callback is the way to format the data labels. If you want to show the top N points you should sort the data in a new array and pull the top 5 values. This is an example of how to clone and sort the array and extract the top 5 elements in the formatter call.
let data = [32, 10, 20, 99, 30, 54, 85, 56, 11, 26, 15, 45, 55, 65];
//Copy the array
let temp = data.slice();
// Sort the temp array in descending order
temp.sort((a, b) => b - a);
Highcharts.chart('closed5', {
chart: {
type: 'area',
zoomType: 'x'
},
title: {
text: 'Chart for charting'
},
series: [{
data: data,
dataLabels: {
enabled: true,
formatter: function() {
if (temp.indexOf(this.y) < 5) {
return this.y;
}
},
},
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="closed5"></div>

jqplot chart with data from variable and data from JSON

I'm trying to load data into a jqplot chart via variable, but it's only displaying the first value. I'm lost at to why is doing this.
JavaScript:
$(document).ready(function () {
var sin = [[20, 10, 0, 10, 15, 25, 35, 50, 48, 45, 35, 30, 15, 10]];
var plot = $.plot($(".chart"),
[{ data: sin, label: "sin(x)", color: "#ee7951" }], {
series: {
lines: { show: true },
points: { show: true }
},
grid: { hoverable: true, clickable: true },
yaxis: { min: 0, max: 60 }
});
var previousPoint = null;
$(".chart").bind("plothover", function (event, pos, item) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$('#tooltip').fadeOut(200, function () {
$(this).remove();
});
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
maruti.flot_tooltip(item.pageX, item.pageY, item.series.label + " of " + x + " = " + y);
}
} else {
$('#tooltip').fadeOut(200, function () {
$(this).remove();
});
previousPoint = null;
}
});
});
maruti = {
flot_tooltip: function (x, y, contents) {
$('<div id="tooltip">' + contents + '</div>').css({
top: y + 5,
left: x + 5
}).appendTo("body").fadeIn(200);
}
}
</script>
Ultimately, I would prefer to use JSON format data and use the first value for the chart and the second for the axis.
Data:
[["50.00","3/18/2015 2:00:00 PM"],["37.00","3/12/2015 3:42:44 PM"],["35.00","3/11/2015 3:42:44 PM"]]
Any recommendations or link to samples using this type of data would be greatly appreciated.
The string format was wrong. I ended up using Entity Framework.
So my code behind looks something like:
using (myEntities myEntitiesContainer = new myEntities())
{
var alldata = myEntitiesContainer.myData(id).ToList();
foreach (myData i in alldata)
{
if (alldata.IndexOf(i) == alldata.Count - 1)
{
sb.Append("['").Append(i.DateData.ToString("yyyy-MM-dd HH:mmtt")).Append("', ").Append(i.SomeData.ToString()).Append("]");
}
else
{
sb.Append("['").Append(i.DateData.ToString("yyyy-MM-dd HH:mmtt")).Append("', ").Append(i.SomeData.ToString()).Append("], ");
}
}
myReturnString = sb.ToString();
}
The return string:
[['2015-03-31 16:00PM', 30.00], ['2015-03-31 14:00PM', 40.00], ['2015-03-31 13:00PM', 50.00]]
The Javascript looks like:
var renderGraph = function () {
var plot
var line1 =
plot = $.jqplot('chart', [line1], {
axes: {
xaxis: {
renderer: $.jqplot.DateAxisRenderer,
tickOptions: { min: 0, formatString: '%b %#d' },
tickInterval: '1 day'
},
yaxis: {
tickOptions:{ formatString: '%d'}
}
},
highlighter: {
show: true,
yvalues: 1,
xvalues: 1,
formatString: 'Date: %s Level: %s'
},
cursor: {
show: false,
tooltipLocation: 'sw'
},
legend: {
show: false
}
});
}

Categories plugin for jQuery Flot library not working

I'm making a chart using jQuery Flot library in which x-axis contains text unit (month) instead of number. So I use categories plugin for Flot and clone example code from its main website. But the months does not show, just the bargraph displayed. The code is like following:
The code snippet gets problem is between commented block "site stats chart". I upload full code just for you all know what I am doing and can detect if there is issue in other parts that affect this code snippet.
Flot categories is downloaded from http://www.flotcharts.org/flot/jquery.flot.categories.js
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="ProjectDashboard.aspx.cs" Inherits="SELPORTAL.project.ProjectDashboard" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Project Dashboard</title>
<script type="text/javascript">
pageSetUp();
loadScript("js/plugin/flot/jquery.flot.cust.js", loadFlotResize);
function loadFlotResize() {
loadScript("js/plugin/flot/jquery.flot.resize.js", loadFlotFillbetween);
}
function loadFlotFillbetween() {
loadScript("js/plugin/flot/jquery.flot.fillbetween.js", loadFlotOrderBar);
}
function loadFlotOrderBar() {
loadScript("js/plugin/flot/jquery.flot.orderBar.js", loadFlotPie);
}
function loadFlotPie() {
loadScript("js/plugin/flot/jquery.flot.pie.js", loadFlotCategories);
}
function loadFlotCategories() {
loadScript("js/plugin/flot/jquery.flot.categories.js", loadDebug);
}
function loadDebug() {
loadScript("js/plugin/flot/jquery.flot.debug.js", loadFlotToolTip);
}
function loadFlotToolTip() {
loadScript("js/plugin/flot/jquery.flot.tooltip.js", generateAllFlotCharts);
}
/* chart colors default */
var $chrt_border_color = "#efefef";
var $chrt_grid_color = "#DDD"
var $chrt_main = "#E24913"; /* red */
var $chrt_second = "#6595b4"; /* blue */
var $chrt_third = "#FF9F01"; /* orange */
var $chrt_fourth = "#7e9d3a"; /* green */
var $chrt_fifth = "#BD362F"; /* dark red */
var $chrt_mono = "#000";
var MONTH_NAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
var categories = {};
var ongoingProjects = [];
var issues = {};
$(function () {
var jsonData = $("#projectsYearCategory").val();
parseDataReceived(jsonData);
fillOngoingTable();
});
function parseDataReceived(json) {
var obj = JSON.parse(json);
categories = obj.allProjects;
ongoingProjects = obj.ongoingProjects;
issues = obj.issues;
for (var i = 0; i < ongoingProjects.length; i++) {
ongoingProjects[i].deadline = getDateFromJsonDate(ongoingProjects[i].deadline);
}
for (var category in issues) {
for (var i = 0; i < issues[category].length; i++) {
issues[category][i] = [getTickDateString(getDateFromJsonDate(issues[category][i].Item1)), issues[category][i].Item2];
}
}
console.log(categories);
console.log(ongoingProjects);
console.log(issues);
}
function getDateFromJsonDate(d) {
return new Date(parseInt(d.substr(6)));
}
function getDateString(d) {
return (d.getMonth() + 1) + "/" + d.getDate() + "/" + d.getFullYear();
}
function getTickDateString(d) {
return MONTH_NAMES[d.getMonth()] + "-" + d.getFullYear();
}
function fillOngoingTable() {
var tblBody = $('#tbl_ongoing tbody');
for (var i = 0; i < ongoingProjects.length; i++) {
var row = $('<tr>');
row.append($('<td>').text(ongoingProjects[i].name));
row.append($('<td>').text(ongoingProjects[i].model));
row.append($('<td>').text(ongoingProjects[i].grade));
row.append($('<td>').text(getDateString(ongoingProjects[i].deadline)));
tblBody.append(row);
}
}
function generateAllFlotCharts() {
for (var category in categories) {
var projects = categories[category];
var ongoing = [];
var upcoming = [];
var completed = [];
var drop = [];
for (var year in projects) {
ongoing.push([year, projects[year]["Ongoing"]]);
upcoming.push([year, projects[year]['Upcoming']]);
completed.push([year, projects[year]['Completed']]);
drop.push([year, projects[year]['Drop']]);
}
var ds = new Array();
ds.push({
data: ongoing,
label: "Ongoing",
bars: {
show: true,
barWidth: 0.1,
order: 1,
}
});
ds.push({
data: upcoming,
label: "Upcoming",
bars: {
show: true,
barWidth: 0.1,
order: 2,
}
});
ds.push({
data: completed,
label: "Completed",
bars: {
show: true,
barWidth: 0.1,
order: 3,
}
});
ds.push({
data: drop,
label: "Drop",
bars: {
show: true,
barWidth: 0.1,
order: 4,
}
});
//Display graph
$.plot($("#bar-chart-" + category.toLowerCase()), ds, {
colors: [$chrt_second, $chrt_fourth, "#666", "#BBB"],
grid: {
show: true,
hoverable: true,
clickable: true,
tickColor: $chrt_border_color,
borderWidth: 0,
borderColor: $chrt_border_color,
},
legend: true,
xaxis: {
tickDecimals: 0,
},
yaxis: {
tickDecimals: 0,
min: 0,
},
tooltip: true,
tooltipOpts: {
content: "<span>%s: %y project(s)</span>",
defaultTheme: false
}
});
}
/* pie chart */
if ($('#pie-chart').length) {
var data_pie = [];
var series = Math.floor(Math.random() * 10) + 1;
for (var i = 0; i < series; i++) {
data_pie[i] = {
label: "Series" + (i + 1),
data: Math.floor(Math.random() * 100) + 1
}
}
$.plot($("#pie-chart"), data_pie, {
series: {
pie: {
show: true,
innerRadius: 0.5,
radius: 1,
label: {
show: false,
radius: 2 / 3,
formatter: function (label, series) {
return '<div style="font-size:11px;text-align:center;padding:4px;color:white;">' + label + '<br/>' + Math.round(series.percent) + '%</div>';
},
threshold: 0.1
}
}
},
legend: {
show: true,
noColumns: 1, // number of colums in legend table
labelFormatter: null, // fn: string -> string
labelBoxBorderColor: "#000", // border color for the little label boxes
container: null, // container (as jQuery object) to put legend in, null means default on top of graph
position: "ne", // position of default legend container within plot
margin: [5, 10], // distance from grid edge to default legend container within plot
backgroundColor: "#efefef", // null means auto-detect
backgroundOpacity: 1 // set to 0 to avoid background
},
grid: {
hoverable: true,
clickable: true
},
});
}
/* end pie chart */
/* site stats chart */
if ($("#line-chart-issues").length) {
var issuesSDK = issues["SDK"];
var issuesMobile = issues["Mobile"];
var issuesCamera = issues["Camera"];
console.log(issuesSDK);
console.log(issuesMobile);
console.log(issuesCamera);
var data = [["January", 10], ["February", 8], ["March", 4], ["April", 13], ["May", 17], ["June", 9]];
$.plot("#line-chart-issues", [data], {
series: {
bars: {
show: true,
barWidth: 0.6,
align: "center"
}
},
xaxis: {
mode: "categories",
tickLength: 0
}
});
}
/* end site stats */
}
</script>
</head>
The categories plugin requires an array of categories in the xaxis options:
xaxis: {
mode: "categories",
categories: ["Category One", "Category Two", "Category Three"] // I don't see you doing this anywhere in your code!
}
You just need to update the main library from http://www.flotcharts.org/flot/jquery.flot.js to make all compatible
1:be sure to added this java script to your code
<script language="javascript" type="text/javascript" src="../../jquery.flot.js"></script>
<script language="javascript" type="text/javascript" src="../../jquery.flot.categories.js"></script>
and your function can like this
$(function() {
var data = [ ["January", 10], ["February", 8], ["March", 4], ["April", 13], ["May", 17], ["June", 9] ];
$.plot("#placeholder", [ data ], {
series: {
bars: {
show: true,
barWidth: 0.6,
align: "center"
}
},
xaxis: {
mode: "categories",
tickLength: 0
}
});
});

Test alignment 'Center' to the highchart legend content

I have been working on the highchart for a while, I have the chart like this
and i have placed the legend at the botton of the page and what i need to do is make the legend text align center like in the following image
I found few question of text alignment in highchart but does not suite my request. So I am unable to move further.
Fiddle http://jsfiddle.net/AbNpB/12/
Thanks in Advance!
It's possible to align each line using a custom code that will translate each legend item.
It's easier to resize output window in JSFiddle: http://jsfiddle.net/BlackLabel/a02czac2/
$(function() {
(function(H) {
H.wrap(H.Legend.prototype, 'render', function(proceed) {
// proceed
proceed.apply(this, [].slice.call(arguments, 1));
// custom
var legend = this,
centerRow = function(tab, w, x) {
var offset = (legend.legendWidth - (x + w)) / 2;
H.each(tab, function(elem) {
elem.legendGroup.attr({
translateX: elem.legendGroup.translateX + offset
});
});
}
if (legend.options.centerItemLines) {
var items = legend.allItems || [],
lastY = items[0] && items[0]._legendItemPos[1],
rowItems = [],
pos, prevX, prevW;
H.each(items, function(item) {
pos = item._legendItemPos;
if (pos[1] > lastY) {
lastY = pos[1];
centerRow(rowItems, prevW, prevX);
rowItems = [];
}
rowItems.push(item);
prevX = pos[0];
prevW = item.legendGroup.getBBox(true).width;
});
centerRow(rowItems, prevW, prevX); // last line
}
});
}(Highcharts))
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container'
},
legend: {
itemStyle: {
width: 350
},
centerItemLines: true
},
series: [{
data: [6, 4, 2],
name: 'First'
}, {
data: [7, 3, 2],
name: 'Second a longer legend text and longer and longer and longer'
}, {
data: [9, 4, 8],
name: 'Third'
}, {
data: [1, 2, 6],
name: 'Fourth'
}, {
data: [4, 6, 4],
name: 'Fifth'
}]
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 400px;"></div>
Try to add this one:
legend: {
align: 'center',
verticalAlign: 'bottom',
x: 0,
y: 0
},
Hope this helps.

Categories

Resources