Currently, in amchart4, the legends can be used to show / hide the target series on click. I would like the behaviour wherein on clicking on the legend:
Do not hide the clicked series.
Hide all other series except the one that was clicked so as to show only the seires whose legend that was clicked.
This question is on the back of an older question targetting amcharts3. However, since v4 is significantly different from v3, the answer does not work.
Based on the documentation here, it appears that the below should work:
series1.events.on("hidden", function() {
series2.hide();
series3.hide();
// but when I run series1.show() in order to mimic series1 to not hide, I get a max call size exceeded msg
});
Further to that, according to this, one can outright disable the toggle on the legends - but it works at the cart level and not at the series level.
Thanks.
Update: Follow up is available on GitHub. Posting the update here for the sake of completeness.
#zeroin 's answer works perfectly. I just needed it to be modified a bit more to have it working for the below scenario.
How do I re-enable all the series again? In the graph I'm building, I
have a series called 'allTraffic' and multiple other series.
AllTraffic should never get hidden.
When I click on any of the other series apart from AllTraffic, hide the other series apart from AllTraffic and the series whose legend has been clicked.
Reset everything (bring back all the series) when AllTraffic's legend is clicked.
chart.legend.itemContainers.template.togglable = false;
chart.legend.itemContainers.template.events.on("hit", function(event) {
var target = event.target;
chart.legend.itemContainers.each(function(item) {
if (target.dataItem.dataContext.name != 'All traffic' && item.dataItem.dataContext.name != 'All traffic') {
console.log("clicked other: ", target.dataItem.dataContext.name);
item.isActive = true;
item.dataItem.dataContext.hide();
}
if (target.dataItem.dataContext.name == 'All traffic') {
console.log("Clicked all traffic");
item.isActive = false;
item.dataItem.dataContext.show();
}
});
target.isActive = false;
target.dataItem.dataContext.show();
})
Here is how you do it:
https://codepen.io/team/amcharts/pen/285b315ff30a2740fdbf72f27230711c
To avoid SO you need to make itemContainers not togglable:
chart.legend.itemContainers.template.togglable = false;
chart.legend.itemContainers.template.events.on("hit", function(event){
var target = event.target;
chart.legend.itemContainers.each(function(item){
if(item != target){
item.isActive = true;
item.dataItem.dataContext.hide();
}
})
target.isActive = false;
target.dataItem.dataContext.show();
})
I have datasets from my chart and I want to reorganize to make it look better.
This would be my chart
OriginalChart
and this would be my chart when I remove 2 elements labels from it and the idea would be to reorganize everything and delete the elements with the red boxes that have 0 as value or in other words, to only display data with values different than 0 ...
ChartWithDataToOrganize
the idea would be simple, just filtering all data value that is equal to 0, but I don't really if there is a tool for it but also to reverse it as well when you display all data again.
labels
I achieved to see how to hide elements when clicking on the legends but how can I achieve to hide the data inside which is == 0 and then get it reversed when I unhide it and see it like the first time..
legend: {
display: true,
onClick: function(e, legendItem) {
var index = legendItem.datasetIndex;
var actualChart = this.chart;
//If the actual label is not hidden, I set it up as false, otherwise is null
var alreadyHidden = (actualChart.getDatasetMeta(index).hidden === null) ? false : actualChart.getDatasetMeta(index).hidden;
actualChart.data.datasets.forEach(function(e, i) {
var meta = actualChart.getDatasetMeta(i);
if (i === index) {//I check if the selected label is already hidden otherwise I hide it
if(!alreadyHidden){
meta.hidden = true;
}else{
meta.hidden = null;
}
}
});
actualChart.update();
},
},
I'm using ChartJs 2.8.0
on Chrome
I did not put any data entry as labels are just names and the others returnData() are just %
I managed to do it by creating a copy of the actual copy of my datasetsLabels and set up the new configuration and in case I show again the selected label I just replace the new dataSetLabel for the previous dataset that I had before.
I have a single vector layer in OpenLayers 4 (4.4.1). The layer has several features with LineString geometries. Some of the features overlap.
If I click at a point where features overlap, I want only one of the features to be drawn as selected. The others should still be available for selection later (by feature id in a separate UI selection list).
If I click on another feature id (in the separate UI selection List) that feature should be drawn as selected, and the previously selected should not be drawn as selected, but still available in the selection list.
This works, but it is only the first (default) selected feature that seems to be drawn at the top.
Image below shows when feature id 10049 is marked as selected.
Image below shows when feature id 10048 is marked as selected.
If I click somewhere on the southmost feature where they do not overlap, it is drawn correctly as selected on top.
To keep track of the feature that needs to be visually selected there is a variable:
var multiselectPrimaryId = 0;
I use the following selectInteraction code:
selectInteraction.on('select', function (e) {
e.deselected.forEach(function (feature) {
feature.setStyle(null);
});
if (e.selected.length <= 1) {
$("#multipleHitWindow").hide();
multiselectPrimaryId = 0;
if (e.selected.length == 0) {
return;
}
}
var features = e.selected;
if (multiselectPrimaryId == 0) {
multiselectPrimaryId = features[0].getId();
}
if (features.length > 1) {
var text = "Multiple hits: ";
features.forEach(function (elem, index, array) {
text += "<a href='javascript:changeSelectedFeature("
+ elem.getId() + ")'>" + elem.getId() + "</a> ";
if (elem.getId() == multiselectPrimaryId) {
elem.setStyle(selectedStyleFunction);
}
});
$('#multipleHit').html(text);
$("#multipleHitWindow").show();
}
else {
features[0].setStyle(selectedStyleFunction);
}
});
And I call this function from a dynamically created list of link:
function changeSelectedFeature(id) {
multiselectPrimaryId = id;
var featuresArray = selectInteraction.getFeatures().getArray().slice(0);
var event = new ol.interaction.Select.Event()
event.deselected = featuresArray;
event.selected = featuresArray;
event.type = 'select';
event.target = selectInteraction;
event.mapBrowserEvent = map.mapBrowserEventHandler_;
selectInteraction.dispatchEvent(event);
}
How can I get the one with selectedStyle set to be drawn at the top? I have tried to add a zIndex to the selectedStyle. But it does not seem to have any effect.
Here is a JsFiddle: https://jsfiddle.net/5j6c6mgo/7/ . There are some other minor issues with the selection, but hopefully you will able to see the behaviour that I described above.
I have a single vector layer ... The layer has several features with LineString geometries. Some of the
features overlap.
I think you would need the LineString geometries to be in separate Layers for you to be able to use 'zIndex' - you would do this by calling 'setZIndex' on the layer in question. This will easily allow you to set the draw order at runtime.
Other than that the vectors are going to be displayed in their initial draw order and short of redrawing changing their draw order isn't possible.
I got a HighChart with several 2 series.
Now I want certain points in series 1 to be disabled when I click a link.
This is my code so far:
$('.remove').click(function () {
var chart = $('#plot').highcharts(),
series = chart.series[0];
if (series.data.length) {
chart.series[0].data[0].remove();
}
});
The problem is, that after removing this point, [0] changes to another value and after clicking it again, it goes on and on with deleting.
I just want the points to disappear, this is possible with visible:
visible Since 1.2.0 Read only. The series' visibility state as set by
series.show(), series.hide(), or the initial configuration.
But I just don't manage to implement it the right way in my onClick event.
If I understand you well, you need to keep "place" where the point was? If yes, you can try to use point.update() function and set null value.
Example: http://jsfiddle.net/gd4q4jo0/1/
I solved clicks on a link to delete points like this:
$('.remove').click(function () {
var series = chart.series[0];
var id = $(this).data('id');
if (series.data.length) {
// disable point in graph
chart.series[0].data[id-1].update(
{
y:null
});
}
// delete used tablerow
$(this).closest("tr").fadeOut(50);
});
And I managed to expulse points onClick on the graph with an event, it's working like this:
series: [{
name: 'time',
data: data: [[1, 129386],[2, 123966],[3, 123162],[4, 123245],[5, 124314],[6, 123946],[7, 124156],[8, 123367],[9, 124460],[10, 123366],[11, 123182],[12, 123915],[13, 124627],[14, 123142],[15, 124044],[16, 124346],[17, 123156],[18, 124356],[19, 123511],[20, 124239],[21, 123252],[22, 125169],[23, 125027],[24, 123508],[25, 124065],[26, 122719],[27, 124199],[28, 122968],[29, 124132],[30, 124052],[31, 124383],[32, 123265],[33, 124083],[34, 123855],[35, 124284],[36, 123719],[37, 123213],[38, 124245],[39, 123079],[40, 123721]],
events: {
// if point gets clicked, it'll be deleted
click: function(event) {
console.log(event.point);
var pointId = event.point.x;
$("#hidden-points-table").fadeIn(1000);
$('#hidden-elements').append(pointId + ", ");
event.point.update(
{
y: null
});
// deleting the table row
$("[data-id='"+pointId+"']").closest("tr").fadeOut(50);
}
}
}
Since it was hard to find solutions, I hope this will help some people with it.
This page was really helpful, too.
I`m trying to add options to my select menu in my custom plugin. I want to get these options from array that I have and with forearch or for to create these options.How can I do that?
Could you show us your code that generates the select box? If I'm guessing right, you might be able to do something like
var things = [];
var your = ["Derpy","Fluttershy","Applejack"];
for(var i = 0; i < your.length; i++) {
// The two values used to separate actual and display values if needed
things[i] = [your[i],your[i]];
}
// snip snip
tab.add({
type: 'select',
label: 'myAwesomePonySelector',
id: 'myAwesomePonySelector',
items : things
// your other definitions, like onShow and commit
});
I hope this helps.