I'm trying to create a custom credits with a tooltip, I've found and example of setting an event listener to title and add tooltip to chart title using mouseover. But for some reason adding this event listener doesn't seem to work with my custom label created with SVGRenderer, what am I missing??
My attempt: https://jsfiddle.net/bernardo0marques/ovhx39c8/10/
Notice that in your example, in the load callback you are trying to add a custom event to the label which doesn't exist because it wasn't rendered yet.
Check console: https://jsfiddle.net/BlackLabel/u07y5gnr/
To fix it, add this logic after rendering this label: https://jsfiddle.net/BlackLabel/p4mL23yr/
chart: {
events: {
render: function() {
let chart = this,
credits = chart.options.credits;
// keep label responsive
if (chart.customLabel) chart.customLabel.destroy();
chart.customLabel = chart.renderer
.label('my custom text', 0, 0).css(credits.style)
.add();
chart.customLabel.translate(chart.plotWidth, chart.chartHeight - chart.customLabel.getBBox().height)
chart.customLabel.on('mouseover', e => {
chart.myLabel = this.renderer.label(this.title.textStr, e.x - 75, e.y - 50, 'rectangle')
.css({
color: '#FFFFFF'
})
.attr({
fill: 'rgba(0, 0, 0, 0.75)',
padding: 8,
r: 4,
})
.add()
.toFront();
});
chart.customLabel.on('mouseout', e => {
if (chart.myLabel) {
chart.myLabel.destroy();
}
})
}
},
},
Related
We are using Chart.js (version 2.6.0) for a bar chart in an Angular 5 application and the client wanted us to disable hover events for chart interactions(they only wanted the bar to change and the tooltips to show up when the user clicked on a bar).
in the bar chart options object, we have the following defined for the events property:
events: ["touchstart","touchmove","click"]
That disables hovering events over the bar chart. Now however, the client wants us to change the cursor to a pointer when the user hovers over one of the bars, so that they know they can click on it, which is a valid point. I've found several solutions here on SO, but I can't seem to find a way to do it without adding "mousemove" to the events property, which just enables hovering interactions on the entire chart.
What really confuses me is that options.hover has an event property called "onHover" that has a callback, but it fires when ANY of the defined events happens, including clicks.
http://www.chartjs.org/docs/latest/general/interactions/events.html
Is this even possible without re-enabling the hover interaction in general? Any help would be greatly appreciated.
With Chart.js 3.x:
onHover: (event, chartElement) => {
event.native.target.style.cursor = chartElement[0] ? 'pointer' : 'default';
}
With Chart.js 2.x:
onHover: (event, chartElement) => {
event.target.style.cursor = chartElement[0] ? 'pointer' : 'default';
}
Based on #Luca Fagioli answer, in my case, I didn't want to disable the click events in my chart so i added:
events: ['mousemove', 'click'],
onHover: (event, chartElement) => {
event.target.style.cursor = chartElement[0] ? 'pointer' : 'default';
}
now that you have a cursor on the chart you want the cursor in the legend too - if they are clickable - so in the legend settings toy hold add:
onHover: (event) => {
event.target.style.cursor = 'pointer';
}
For versions > 3.x
you find the target under native
options: {
plugins : {
legend: {
labels: {
onHover: function (e) {
e.native.target.style.cursor = 'pointer';
},
onLeave: function (e) {
e.native.target.style.cursor = 'default';
}
}
}
}
}
This is almost 5 years old question, using the version 3.x.x of ChartJS we just need to declare some event handlers like onHover, onClick and define the events handle by the tooltip like events: ['click'].
Here we have a working snippet:
const isArray = a => a instanceof Array
const isNull = a => a == null
const cursor = a => {
if (isNull(a)) return 'default'
if (!isArray(a)) return 'pointer'
if (isArray(a) && a.length > 0) return 'pointer'
return 'default'
}
const $canvas = document.getElementById('chart')
const onHover = (e, item) => {
$canvas.style.cursor = cursor(item)
}
const onLeave = () => {
$canvas.style.cursor = 'default'
}
const onClick = (event, items) => {
if (items.length === 0) return
console.log('onclick')
}
const lineChart = new Chart($canvas, {
type: 'bar',
data: {
labels: ['May', 'June', 'July'],
datasets: [{
data: [15, 25, 15],
label: "My Dataset1",
backgroundColor: "#00F",
fill: false
}, {
data: [35, 15, 25],
label: "My Dataset2",
backgroundColor: "#F00",
fill: false
}]
},
options: {
responsive: true,
onHover,
onClick,
plugins: {
tooltip: {
// Tooltip will only receive click events
events: ['click'],
},
legend: {
onHover,
onLeave,
},
},
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<canvas id="chart" width="600" height="180"></canvas>
I have UML state diagram drawn using jointjs and the various states are connected through links. On hovering over the links, a cross symbol appears upon clicking which the link gets removed. I want to disable the cross symbol over the link.
You will need to create a custom link extending from joint.dia.link and use that link for your charts. Look into joint.core.js for more details and joint.shapes.uml.js
Step1. Create your custom uml link either by extending directly from joint.dia.link or by extending from the below
joint.shapes.uml.Generalization
joint.shapes.uml.Implementation
joint.shapes.uml.Aggregation
joint.shapes.uml.Composition
joint.shapes.uml.Association
joint.shapes.yourLink = joint.dia.Link.extend({
//to remove the cross that removes the link modify the toolMarkUp to not show anything as below and use your new link
toolMarkup: [
].join(''),
add the remaining attributes that you currently have for the link like source, target etc
})
sample code from my project
joint.shapes.deviceLink = joint.dia.Link.extend({
// i modified the vertexMarkup to not create vertexes.
vertexMarkup: [
'<g class="marker-vertex-group" transform="translate(<%= x %>, <%= y %>)">',
'<circle class="marker-vertex" idx="<%= idx %>" r="1" />',
'</g>'
].join(''),
defaults: joint.util.deepSupplement({
type: 'deviceLink',
connection: { name: 'orthogonal' },
attrs: {
'.connection': { stroke: '#fe854f', 'stroke-width': 3 },
sourcePort:{text:''},
targetPort:{text:''},
'.link-tools .tool-remove circle': { r: 8, fill:'#fff',position: 0.5 },
},
labels: [ { position: 0.5, attrs: { text: { text: '' } } } ]
}, joint.dia.Link.prototype.defaults),
});
joint.shapes.deviceLinkView = joint.dia.LinkView.extend({
mouseover: function (evt, x, y) {
//my custom mouseover function
},
mouseout: function (evt, x, y) {
// my custom mouseout function
});
I am trying to integrate snap.svg in to Enyo and having a problem. The code below works, until render() is called. The problem seems to be that generateHtml in HTMLStringDelegate.js doesn't know about the content added by snap.svg and clears out "svg".
Uncomment "this.render();" to see it.
http://jsfiddle.net/Kloodge/g7MLS/2031/
var ready = require('enyo/ready'),
kind = require('enyo/kind'),
Toolbar = require('onyx/Toolbar'),
Application = require('enyo/Application');
ready(function() {
var MySample = kind({
name: "MySample",
paper: null,
components: [
{kind: Toolbar, content: "Your sample here."},
{tag: "svg", name:"svg"}
],
rendered: function(){
this.inherited(arguments);
if(!this.paper && this.$.svg.hasNode()){
this.paper = Snap("#"+this.$.svg.hasNode().id);
circle = this.paper.circle(10, 10, 10);
circle.attr({
fill: "#bada55",
stroke: "#000",
strokeWidth: 5,
});
//this.render();
}
}
});
new Application({view: MySample});
});
Is there any way to do this short of adding the content statically to "svg"?
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.
I would like to add a label to a link by doing a doubleclick on the link. So this is my attempt:
paper.on({
'cell:pointerdblclick': function(cellView, event, x, y){
if (cellView.model.isLink()) {
cellView.model.label(0, {
position: .5,
attrs: {
rect: { fill: 'white' },
text: { text: 'my label' }
}
});
}
},
});
The problem is, that by doing a doubleclick there is also a vertex beeing created at the same time. How can I prevent that?
Or what would be another simple way to let users add a label for a link?
As shown in the docs (http://jointjs.com/api#joint.dia.LinkView:addVertex) just add this part to joint.dia.Paper:
interactive: function(cellView) {
if (cellView.model instanceof joint.dia.Link) {
// Disable the default vertex add functionality on pointerdown.
return { vertexAdd: false };
}
return true;
}