Highcharts : On drillup, how can I unselect my selected point? - javascript

I'm using a chart with drilldown and I've allowed to select a point (=click). On the event click, I create an HTML table with help of AJAX to list the entities related to the count (if I see 5 items, by clicking on it I'll see who are the 5 items and list them). This becomes a 2nd/3rd level of drilldown (depending I've clicked on the 1st level of 2nd level in the chart)
However, I'd like to remove the selection on first level on the drill up event.
Here is my code (EDITED) :
Edit
I'm adding series like this (sample found here) :
$(function() {
var myChart = new Highcharts.Chart({
chart: {
type: 'column',
renderTo: 'drillDownContainer',
// Deactivate drilldown by selection.
// See reason below in the drilldown method.
selection: function(event) {
return false;
},
drilldown: function(e) {
// Deactivate click on serie. To drilldown, the user should click on the category
if (e.category === undefined)
{
return;
}
// Set subTitle (2nd param) by point name without modify Title
// Giving 1st param as null tells the text will be for the subTitle,.
// For Title, remove the null 1st param and let text.
this.setTitle(null, { text: e.point.name });
if (!e.seriesOptions) {
var chart = this,
drilldowns = {
'Social': [
{"name":"Serie 1","data": [{"id":113,"name":"my data","y":14}
]}
]
};
var categorySeries = drilldowns[e.point.name];
var series;
for (var i = 0; i < categorySeries.length; i++) {
if (categorySeries[i].name === e.point.series.name) {
series = categorySeries[i];
break;
}
}
chart.addSingleSeriesAsDrilldown(e.point, series);
drilldownsAdded++;
// Buffers the number of drilldown added and once the number of series has been reached, the drill down is applied
// So, can't navigate by clicking to a single item.
// However, simply click on the category (xAxis) and then unselect the other series by clicking on legend
// The click has been disabled.
if (drilldownsAdded === 3) {
drilldownsAdded = 0;
chart.applyDrilldown();
}
}
},
drillup: function(e) {
this.setTitle(null, { text: '' }); // Erase subTitle when back to original view
$('#ajaxContainer').html(''); // Remove the table drilldown level3
},
drillupall: function(e) {
debugger;
console.log(this.series);
console.log(this.series.length);
for(i = 0; i < this.series.length; i++)
{
console.log("i = " + i);
console.log(this.series[i].data.length);
for (d = 0; i < this.series[i].data.length; d++)
{
console.log("d = " + d);
console.log(this.series[i].data[d].selected);
}
}
}
}
}); -- End of myChartdeclaration
myChart.addSeries({
color: colorsArray['impact101'],
name: '1-Modéré',
data: [
{
id: '101',
name: 'Type 1',
y: 64,
drilldown: true
},
{
id: '102',
name: 'Type 2',
y: 41,
drilldown: true
}]
}, true);
});
Demo of the point selection : http://jsfiddle.net/8truG/12/
What do I'd like to do? (EDIT)
If I select a point on the 2nd level, then return to 1st level and then back to same drilldown data, the point selected before is not selected anymore.
However, for the 1st level, the selection remains.
On the drillup event, the this.series[x].data[y] corresponds to the data of the 2nd level. Kind of obvious as the drilldown is not finished for all series but event raised as many as there is series.
On the drillupall event, I'm getting the right serie. I can see my 3 series on debug but they are all without any data. So I can't apply this.series[i].data[d].selected as suggested in comment below.
I'm using Highcharts 5.0.9.
Any idea to help me ?
Thanks for your help.

I got helped on the Highcharts forum. See here.
Here is the answer (in case the link above doesn't work in the future):
In this case you can change the state of a specific point with
Point.select() function. Take a look at the example posted below. It
works like that: in drillup() event there is a call of
getSelectedPoints() which returns all selected points from the base
series. Next, there is a call of select() function with false as an
argument on a selected point to unselect it. In addition, the call of
the getSelectedPoints() is located in a timeout, otherwise it would
return an empty array (see
https://github.com/highcharts/highcharts/issues/5583).
CODE:
setTimeout(function() { selectedPoints =
chart.getSelectedPoints()[0];
chart.getSelectedPoints()[0].select(false); }, 0);
API Reference: http://api.highcharts.com/highcharts/Ch ... ctedPoints
http://api.highcharts.com/highcharts/Point.select
Examples: http://jsfiddle.net/d_paul/smshk0b2/
Consequently, here now the code fixing the issue :
drillupall: function(e) {
this.setTitle(null, { text: '' }); // Erase subTitle when back to original view
$('#ajaxContainer').html(''); // Remove the table drilldown level3
var chart = this,
selectedPoints;
setTimeout(function() {
selectedPoints = chart.getSelectedPoints()[0];
// Ensure there is any selectedPoints to unselect
if (selectedPoints != null)
{
selectedPoints.select(false);
}
}, 0);
Regards.

Related

vis.js hyperlink an edge

Is it possible to get a hyperlink to work on an edge?
Example, I have two nodes that are connected, And have a label on them
{ id: 1601, label: 'label', x: -1085, y: -429, url: 'link' },
So for the above, The url works for the node when using
this option
network.on("selectNode", function (params) {
if (params.nodes.length === 1) {
var node = nodes.get(params.nodes[0]);
window.open(node.url, '_blank');
}
});
Now I have a link between two nodes using the standard config
{ from: 1600, to: 1613, label: "label value" },
Is it possible to get a huperlink to work on the lines / edge that connections the two nodes?
Basically, changing "node" to "edge" in your code works to open the url when an edge is selected. But, selecting a node also results in selecting all the adjacent edges. You only get one selectEdge callback, but probably want to ignore it in any case. If you want to rule out the case where someone selected the node, where there happens to be just one connected edge, then add a check for that as follows:
network.on("selectEdge", function(params) {
if ((params.edges.length == 1) && (params.nodes.length == 0)) {
var edgeId = params.edges[0];
window.open(edges.get(edgeId).url, '_blank');
}
});
There's still a problem in using "select" for this. If you have previously selected a node, then the adjacent edges are selected, even if you don't see it because of the checking above. If you then click on one of those adjacent edges, you don't get the callback because that edge was already selected. It might be better to use the network.on("click" ... ) method instead:
network.on("click", function(params) {
if (params.nodes.length == 1) {
var nodeId = params.nodes[0];
if (nodes.get(nodeId).url != null) {
window.open(nodes.get(nodeId).url, '_blank');
}
} else if (params.edges.length==1) {
var edgeId = params.edges[0];
if (edges.get(edgeId).url != null) {
window.open(edges.get(edgeId).url, '_blank');
}
}
});

How to show Total number of pages in YUI Paginator?

I am using YUI Paginator API for pagination and I need to show Total number of pages on screen. I saw that there is a function getTotalPages() in API but I am unsure about how to use it, there isn't enough documentation. Also after looking at some other documentation I tried using {totalPages} but didn't work.
Can somebody help me out in this issue? Thanks in advance!!
Below is the code snippet I am using. Please refer to template object from config:
config = {
rowsPerPage: 100,
template :
'<p class="klass">' +
'<label>Total pages: {totalPages}</label>'+
'<label>Page size: {RowsPerPageDropdown}</label>'+
'</p>',
rowsPerPageDropdownClass : "yui-pg-rpp-options",
rowsPerPageOptions : [
{ value : 100 , text : "100" },
{ value : 250 , text : "250" },
{ value : 500 , text : "500" },
{ value : 1000 , text : "1000" },
{ value : tstMap[tabName].length , text : "All" }
],
};
var myPaginator = new YAHOO.widget.Paginator(config);
The Paginator utility allows you to display an item or a group of items depending on the number of items you wish to display at one time.
Paginator's primary functionality is contained in paginator-core and is mixed into paginator to allow paginator to have extra functionality added to it while leaving the core functionality untouched. This allows paginator-core to remain available for use later on or used in isolation if it is the only piece you need.
Due to the vast number of interfaces a paginator could possibly consist of, Paginator does not contain any ready to use UIs. However, Paginator is ready to be used in any Based-based, module such as a Widget, by extending your desired class and mixing in Paginator. This is displayed in the following example:
YUI().use('paginator-url', 'widget', function (Y){
var MyPaginator = Y.Base.create('my-paginator', Y.Widget, [Y.Paginator], {
renderUI: function () {
var numbers = '',
i, numberOfPages = this.get('totalPages');
for (i = 1; i <= numberOfPages; i++) {
// use paginator-url's formatUrl method
numbers += '' + i + '';
}
this.get('boundingBox').append(numbers);
},
bindUI: function () {
this.get('boundingBox').delegate('click', function (e) {
// let's not go to the page, just update internally
e.preventDefault();
this.set('page', parseInt(e.currentTarget.getContent(), 10));
}, 'a', this);
this.after('pageChange', function (e) {
// mark the link selected when it's the page being displayed
var bb = this.get('boundingBox'),
activeClass = 'selected';
bb.all('a').removeClass(activeClass).item(e.newVal).addClass(activeClass);
});
}
});
var myPg = new MyPaginator({
totalItems: 100,
pageUrl: '?pg={page}'
});
myPg.render();
});

Highcharts - get visible series name dynamically

I want to make a function which send dynamically all visible series name in a Highchart instance to a PHP function.
For example, in this chart, I want to get this array : [Salle, PR].
If I click on Internet, the serie become visible and I want to get [Salle, Internet, PR].
To do this, I tried to use legendItemClick event and make a function that check if each serie is visible to add it to an array but I can't figure out how to use the visible option to do this.
Do you have an idea ?
As of now, I don't have much code to share :
plotOptions: {
series: {
events: {
legendItemClick: function(){
}
}
}
}
If you retain the pointer to your chart like this:
var ch = Highcharts.chart(_chart_data_);
Then later you can access the whole chart structure. What you will be interested in is the series array.
ch.series[]
It contains array of all your series. Series with visible attribute set to true are the ones that currently displayed. So,it might be something like this:
var ch = Highcharts.chart(...
plotOptions: {
series: {
events: {
legendItemClick: function(){
ch.series.forEach(function(sr){
if(sr.visible){
console.log(sr.name, "visible!");
}
});
}
}
}
}
...);
However, there is a catch with your approach, that on actual legend click your current action for the legend is not yet processed.so the output you will see is the output for the previous state, before current click.
So for that reason you may try to use setTimeout to get your listing after the event is applied:
events: {
legendItemClick: function(){
setTimeout(
function(){
ch.series.forEach(
function(sr){
if(sr.visible){
console.log(sr.name, "visible!");
}
}
)
},20);
}
}
Try this and check the console log: http://jsfiddle.net/op8142z0/

angular ui-grid highlight entire row by cell click

It looks like a simple task, but I already spent 4 hours to find a solution. How can I highlight the entire row by cell click?
On register api I have next
$scope.gridOptions.onRegisterApi = function(gridApi){
$scope.gridApi = gridApi;
gridApi.cellNav.on.navigate($scope,function(selected){
if('.ui-grid-cell-focus '){
console.log("fired class")
$(selected.row.entity).addClass('ui-grid-cell-focus')
}
console.log("fired cell")
$(selected.row.entity).addClass('ui-grid-cell-focus')
});
};
I see how click on cell is fired, but I cannot force to color the row and I don't want to select the row, because I use check box selection for this purpose, I just want to highlight the row by click on any cell in this row. Could somebody tell me where my mistake is?
Attached plunker
One way to accomplish what you want is to add a cellClass definition to your columnDefs. That function takes two params: grid and row.
$scope.gridOptions.columnDefs = [{
name: 'id',
width: '150',
cellTemplate: "",
cellClass: getCellClass
}, {
name: 'name',
width: '200',
cellClass: getCellClass
} ...
];
function getCellClass(grid, row) {
return row.uid === selectedRow ? 'highlight' : '';
}
On click you could set a variable to the uid of the row, and inside the cellClass function you can check if the uid of the current row matches the uid of the selected, if so, you can set the class to a class that properly reflects the background color of the selected row.
var selectedRow = null;
gridApi.cellNav.on.navigate($scope, function(selected) {
if ('.ui-grid-cell-focus ') {
selectedRow = selected.row.uid;
gridApi.core.notifyDataChange(uiGridConstants.dataChange.COLUMN);
}
});
Here's a link to your updated plunker: http://plnkr.co/edit/AgpAI2cmdqgNsSLVNjYA?p=preview
If you don't like the cellClass approach you could define custom cellTemplates and similarly react to a property you set on the row entity.

JQVMAP selected regions deselect with JSFIDDLE Demo

Ok I have a JQVMAP that I have on my site to select states for a search box. Everything worked great until I added my Clear function.
I also had to incorporate the patch from member HardCode Link to the patch
Found the solution, change line 466 in jqvmap.js file to:
regionClickEvent = $.Event('regionClick.jqvmap');
jQuery(params.container).trigger(regionClickEvent, [code, mapData.pathes[code].name]);
This is how I initialize it:
// with this Code it will select states and change the color of selected states plus save the codes of selected states into a hidden field
$('#omap').vectorMap(
{
map: 'usa_en',
backgroundColor: '#fff',
borderColor: '#000',
borderWidth: 4,
color: '#f4f3f0',
enableZoom: false,
hoverColor: '#fece2f',
hoverOpacity: null,
normalizeFunction: 'linear',
scaleColors: ['#b6d6ff', '#005ace'],
selectedColor: '#db9b15',
selectedRegion: null,
showTooltip: true,
multiSelectRegion: true,
onRegionClick: function(element, code, region) {
if(highlight[code]!=='#db9b15'){
highlight[code]='#db9b15';
origin = $('#search_origin_states');
states = origin.val();
if (states == ""){
origin.val(code);
} else {
origin.val(states + "," + code);
}
} else {
highlight[code]='#f4f3f0';
states = origin.val();
if (states.indexOf(","+code) >= 0) {
states = states.replace(","+code,"");
origin.val(states);
} else if (states.indexOf(code+",") >= 0){
states = states.replace(code+",","");
origin.val(states);
} else {
states = states.replace(code,"");
origin.val(states);
}
}
$('#omap').vectorMap('set', 'colors', highlight);
}
});
I use to have to click each state to clear it. But I wrote a script to clear all in one click.
function search_map_clear(field, map) {
var states = $('#search_' + field + '_states');
var sel_states = states.val();
var highlight2 = [];
$.each(sel_states.split(','), function (i, code) {
highlight2[code] = '#f4f3f0';
$('#' + map).vectorMap('set', 'colors', highlight2);
});
states.val("");
}
This will change all colors back to the original color, but apparently it does not clear the selectedRegions because after clearing if I select any other state all the states that I changed back to original color show back up.
My Question is:
How can I clear the selected states so were I can select different ones without clicking on every state that was selected prior
UPDATE
I have been able to run this command from the console and I can select and deselect states... But it will not deselect a state that was clicked on to select.
$('#omap').vectorMap('select', 'ar');
$('#omap').vectorMap('deselect', 'ar');
I need to clear out the states that have been clicked on...
Here is my jsFiddle that will show you what is happening:
JSFIDDLE DEMO
You store information in the variable highlight, and you clean the map with highlight2. It will not change the information in highlight so that when you trigger onRegionClick() it will change back to what you select.
Use global variable to let the scope of highlight to cross two script, then replace highlight2 by highlight and remove highlight2 declation.
See jsfiddle here, I think this is what you want.
I just added this function to library
setSelectedRegions: function(keys){
for (var key in this.countries) {
this.deselect(key, undefined);
}
var array = keys.split(",");
for (i=0;i<array.length;i++) {
//alert(array[i])
this.select(array[i], undefined);
}
},
and used it later as
jQuery('#vmap').vectorMap('set', 'selectedRegions', 'gb,us');

Categories