I'm trying to prevent the default behavior when I click on the angular-nvD3 Stacked Area Chart. I managed to access the onclick function, but I don't know how to prevent the event (modifies the graphic) from happening. I don't want the graphic to change when the user clicks on it.
.js:
$scope.stackedAreaChartOptions = {
chart: {
type: 'stackedAreaChart',
height: 450,
margin : {
top: 20,
right: 20,
bottom: 30,
left: 40
},
x: function(d){return d[0];},
y: function(d){return d[1];},
useVoronoi: false,
clipEdge: true,
duration: 100,
useInteractiveGuideline: true,
xAxis: {
showMaxMin: false,
tickFormat: function(d) {
return d3.time.format('%H:%M')(new Date(d))
}
},
yAxis: {
tickFormat: function(d){
return d3.format(',.2f')(d);
}
},
zoom: {
enabled: false,
scaleExtent: [1, 10],
useFixedDomain: false,
useNiceScale: false,
horizontalOff: false,
verticalOff: true,
unzoomEventType: 'dblclick.zoom'
},
//chart events
stacked: {
dispatch: {
areaClick:
function (t,u){ null; console.log("areaClick");}
,
areaMouseover:
function (t,u){ null; console.log("areaMouseover");}
,
areaMouseout:
function (t,u){null; console.log("areaMouseout");}
,
renderEnd:
function (t,u){null; console.log("renderEnd");}
,
elementClick:
function (t,u){null; console.log("elementClick");}
,
elementMouseover:
function (t,u){null; console.log("elementMouseover");}
,
elementMouseout:
function (t,u){ null;console.log("elementMouseout");}
}
},
controlLabels: {stacked:"Absoluto", expanded:"Relativo"},
controlOptions:
[
"Stacked",
false,
"Expanded"
]
},
title: {
enable: true,
text: '',
css: {
'font-weight': 'bold'
}
},
caption: {
enable: true,
html: 'Visualización por horas de acceso a noticia',
css: {
'text-align': 'center',
'margin': '2px 13px 0px 7px',
'font-style': 'italic'
}
}
};
HTML:
<nvd3 options="stackedAreaChartOptions" data="stackedAreaChartData" api="api"></nvd3>
When I click on the graphic, the messages (console.log) are being shown, but I need to prevent the click event from happening.
I know this is an old question, but I run into this problem for my project and here is how I solved it.
It seems it's not possible to disabled these events using angular-nvd3. You must disable them using NVD3.
Get the chart api object available on your angular-nvd3 chart and disable the events on the chart object binded to this api:
HTML
<nvd3 options="options" data="data" api="chartAPI"></nvd3>
Javascript
$timeout( function() {
if ($scope.chartAPI) {
var chart = $scope.chartAPI.getScope().chart;
chart.stacked.dispatch.on('areaClick.toggle', null);
chart.stacked.dispatch.on('areaClick', null);
}
}, 1000);
I made a timeout be sure to have the chartAPI when doing the changes.
Note : It seems you have to disable these events again when you update or refresh the chart (chart.refresh()).
Working example here: https://codepen.io/mvidailhet/pen/JNYJwx
It seems there is a glitch in the chart update on Codepen, but you get the point :)
Hope it helps!
You were close. CSS pointer-events:none; has the disadvantage that it turns off every pointer event (most importantly hover, mouseenter and mouseout).
So IMHO you should avoid to use it.
Actually you were close. You should not pass an it-does-nothing function but null or undefined instead to options.chart.stacked.dispatch.areaClick. Like this:
//chart events
stacked: {
dispatch: {
areaClick: void 0
}
}
I had this very same problem and spent more than an hour to find it out.
EDIT
Turned out that I was wrong. It solved just because it ran into an error that prevented the event. So you can throw an error and everything is fine... :)
Also found a workaround but that causes memory leak, so I'll not share that.
My solution was: accept that it applies click event and hides all other layers. Too small issue to invest more time and effort in it.
Related
I have an existing highchart on which I need to highlight a single column.
It is a percentile graph that has been around for a while, I am still pretty new to high charts, but I have seen a similar question here on SO, this question, though deals with stacked bars and a click event...
The code makes sense to me in the example, but I guess I am missing something,
Here is my sample (trying to highlight the 24th column)
https://jsfiddle.net/52t43y3k/2/
Here is the question I saw:
Highlight one bar in a series in highcharts?
for ref, my code is
var col_chart = $('#section-2-chart').highcharts({
chart: {
type: 'column'
},
tooltip: { enabled: false },
credits:false,
title: false,
xAxis: {
title:{text:'PERCENTILES'},
type: 'Percentile',
labels: {
enabled:true,
formatter: function() {
return this.value*2;
}
}
},
yAxis: {
min: 0,
title:{text:'Total Image Weight'}
},
legend: {
enabled: false
},
series: [{
data: [169,12003,38308.5,61739.7,97069,131895.5,161086.7,198758.7,219779.3,243567.7,276607.7,296931.5,327457.5,362840.3,383978,410685.5,443774,467039.5,491654,517205,544754.7,578468.3,605392.5,644214.5,693765,766953.7,806616,855380.7,894161,942282,1001179.7,1062697.7,1125773.3,1186437,1236893.7,1314379.5,1378944,1454090.3,1553065,1689346,1833150,1957396,2077851.5,2228644.7,2390102,2725365.5,3147844.3,3607372,4239281.5,5190061,9422370.8],
tooltip: {
pointFormat: '<b>{point.y:f} Bytes</b>'
}
}]
});
//TRIED THIS AND series.data[24] - essentially the 24th bar should be highlighted
col_chart.series[0].data[24].update({color:'red'});
You need to access the highcharts off of your jquery object:
col_chart.highcharts().series[0].data[24].update({
color: 'red'
});
For clarity
In your example, the following is true:
console.log(col_chart instanceof jQuery); // true
From the highcharts source:
/**
* Register Highcharts as a plugin in jQuery
*/
if (win.jQuery) {
win.jQuery.fn.highcharts = function () {
var args = [].slice.call(arguments);
if (this[0]) { // this[0] is the renderTo div
// Create the chart
if (args[0]) {
new Highcharts[ // eslint-disable-line no-new
isString(args[0]) ? args.shift() : 'Chart' // Constructor defaults to Chart
](this[0], args[0], args[1]);
return this;
}
// When called without parameters or with the return argument, return an existing chart
return charts[attr(this[0], 'data-highcharts-chart')];
}
};
}
Meaning, highcharts() is a plugin for jQuery, so you can access it (assuming it's been attached to the dom element already, as in your case above) by calling highcharts off a jQuery selector instance.
We are using c3 as a wrapper around d3 javascript charting library. You can see even in their own demo when the data is updated the scroll bar flickers momentarily.
This isn't a problem when there is already a scrollbar on the page as it is in their case. But if the page is smaller the addition and sudden removal or the scrollbar can be jarring.
We aren't doing anything wildly different than they do in their examples. The mystery is why the scrollbars jump. Any ideas? If you want to look at my code it is blow:
Data is getting passed to our AngularJS Directive using SignalR
$scope.$watch('data', function () {
normalizedData = normalize($scope.data);
chart.load({
columns: getChartDataSet(normalizedData)
});
});
After we take the normalized data it simply gets set into an array then passed to C3
var chart = c3.generate({
bindto: d3.select($element[0]),
data: {
type: 'donut',
columns: [],
colors: {
'1¢': '#2D9A28',
'5¢': '#00562D',
'10¢': '#0078C7',
'25¢': '#1D3967',
'$1': '#8536C8',
'$5': '#CA257E',
'$10': '#EC3500',
'$20': '#FF7D00',
'$50': '#FBBE00',
'$100': '#FFFC43'
}
},
tooltip: {
show: true
},
size: {
height: 200,
width: 200
},
legend: {
show: true,
item: {
onmouseover: function (id) {
showArcTotal(id);
},
onmouseout: function (id) {
hideArcTotal();
}
}
},
donut: {
width: 20,
title: $scope.label,
label: {
show: false,
format: function(value, ratio, id) {
return id;
}
}
}
});
body > svg { height: 0; } did not help me. But I had experimented a bit and found a solution:
body > svg {
position: absolute;
z-index: -10;
top: 0;
}
Unfortunately, this method can't fix the issue if a window's height is too small.
Also, you can get rid of jumping by adding scrollbar by default:
body {
overflow-y: scroll;
}
When C3 draws the chart it appends an SVG at the bottom of the <body> element, even with `style="visibility:hidden". I just added a CSS class
body > svg { height:0px !important }
That fixed the issue for me.
I have an HighCharts line plot in which the user can click points using this code:
plotOptions: {
series: {
point: {
events: {
click: function(event) {
// some processing
}
...
I want to change the color of the selected point.
I know that I could write :
marker: {
states: {
select: {
fillColor: 'red',
...
But, in my case, I really need to do this inside click, How can I do it ?
You can always use the update function for that:
plotOptions:{
series:{
marker:{
states:{
select:{
lineColor:'red',
fillColor:'red'
}
}
},
point:
{
events:{
click: function(){
this.setState("select");
this.update({
marker:{
fillColor:'red',
lineColor:'red',
}
})
}
}
}
}
},
When this refers to the point the user clicked.
As you can see, I composed a custom "select" state with some custom properties, and applied this state when user clicks a point. I also used update in order to change the point marker attributes, so I make sure the point reserves the new attributes after the state is no longer active:
http://jsfiddle.net/gprevqdf/2/
I am trying to use jsPlumb to connect questions with answers in a quiz. I have most of this working expect I want to be able to click a question and then click an answer instead of dragging from an endpoint to another endpoint. This is because dragging on a touch device is tedious. Is this possible?
Here is my jsbin with the dragging working
Here is the jquery I am using.
$(document).ready(function () {
var targetOption = {
anchor: "LeftMiddle",
isSource: false,
isTarget: true,
reattach: true,
endpoint: "Rectangle",
connector: "Straight",
connectorStyle: { strokeStyle: "#ccc", lineWidth: 5 },
paintStyle: { width: 20, height: 20, fillStyle: "#ccc" },
setDragAllowedWhenFull: true
}
var sourceOption = {
tolerance: "touch",
anchor: "RightMiddle",
maxConnections: 1,
isSource: true,
isTarget: false,
reattach: true,
endpoint: "Rectangle",
connector: "Straight",
connectorStyle: { strokeStyle: "#ccc", lineWidth: 5 },
paintStyle: { width: 20, height: 20, fillStyle: "#ccc" },
setDragAllowedWhenFull: true
}
jsPlumb.importDefaults({
ConnectionsDetachable: true,
ReattachConnections: true
});
jsPlumb.addEndpoint('match1', sourceOption);
jsPlumb.addEndpoint('match2', sourceOption);
jsPlumb.addEndpoint('match3', sourceOption);
jsPlumb.addEndpoint('match4', sourceOption);
jsPlumb.addEndpoint('answer1', targetOption);
jsPlumb.addEndpoint('answer2', targetOption);
jsPlumb.addEndpoint('answer3', targetOption);
jsPlumb.addEndpoint('answer4', targetOption);
jsPlumb.draggable('match1');
jsPlumb.draggable('answer1');
});
I think if you don't need draggable, then you shouldn't use it, and go with normal click=connect approach.
Here is an example:
http://jsbin.com/ajideh/7/
Basically what I did:
//current question clicked on
var questionSelected = null;
var questionEndpoint = null;
//remember the question you clicked on
$("ul.linematchitem > li").click( function () {
//remove endpoint if there is one
if( questionSelected !== null )
{
jsPlumb.removeAllEndpoints(questionSelected);
}
//add new endpoint
questionSelected = $(this)[0];
questionEndpoint = jsPlumb.addEndpoint(questionSelected, sourceOption);
});
//now click on an answer to link it with previously selected question
$("ul.linematchplace > li").click( function () {
//we must have previously selected question
//for this to work
if( questionSelected !== null )
{
//create endpoint
var answer = jsPlumb.addEndpoint($(this)[0], targetOption);
//link it
jsPlumb.connect({ source: questionEndpoint, target: answer });
//cleanup
questionSelected = null;
questionEndpoint = null;
}
});
When you click on the question list element - it adds endpoint, when you click on the answer element - it also adds endpoint and connects it with previously selected question.
I believe this is what you wanted to do ?
P.S. As a side note, to make this more intuitive for the user, make endpoints for questions visible first, so the user would figure out what to do - click. Once question is selected, available answer endpoints can pop-up hinting where user should click next.
I would like to get the element that called the qtip popup. In the documentation here it lets you set the position. I want to set the position using a jquery selector like $(this).find('.icon'). The problem is that this isn't the element that called the qtip (I think it's window).
Does anyone know how I can get the handle that called it (like it would if I set target to false)?
Thanks.
In the qtip source code I found this:
if(config.position.target === false) config.position.target = $(this);
Here's the solution I came up with and it seems to work. There probably is a better way to do it if I modified the qtip script but I want to leave that alone.
$(".report-error").qtip(
{
content: 'test content',
position:
{
adjust:
{
screen: true
},
target: false, //it is changed in the 'beforeRender' part in api section. by leaving it as false here in the qtip it will set it as the position I need using $(this)
corner:
{
target: 'bottomMiddle',
tooltip: 'topRight'
}
},
show:
{
when:
{
event: 'click'
}
},
style:
{
name: 'cream',
tip:
{
corner: 'topRight'
},
padding: 0,
width: 400,
border:
{
radius: 5,
width: 0
}
},
hide:
{
when:
{
event: 'unfocus'
}
},
api:
{
beforeRender: function() { //get the position that qtip found with $(this) in it's script and change it using that as the start position
this.options.position.target = $(this.elements.target).find('.icon');
this.elements.target = this.options.position.target; //update this as well. I don't actually know what it's use is
}
}
});
It's working on the site now at http://wncba.co.uk/results/