Limiting agRichSelectCellEditor to n-items? - ag-grid
Is there any way to restrict the height (eg to n * .cellHeight) for the built-in agRichSelectCellEditor?
I see there is a cellRenderer but this only affects the individual list-items - I know I can always implement a custom editor but wanted to see if this was possible first
override the CSS rule .ag-rich-select-list
.ag-rich-select-list {
width: 100%;
min-width: 200px;
height: auto !important;
}
var students = [{
first_name: 'Bob',
last_name: 'Harrison',
gender: 'Male',
address: '1197 Thunder Wagon Common, Cataract, RI, 02987-1016, US, (401) 747-0763',
mood: "Happy",
country: {
name: 'Ireland',
code: 'IE'
}
}, {
first_name: 'Mary',
last_name: 'Wilson',
gender: 'Female',
age: 11,
address: '3685 Rocky Glade, Showtucket, NU, X1E-9I0, CA, (867) 371-4215',
mood: "Sad",
country: {
name: 'Ireland',
code: 'IE'
}
}, {
first_name: 'Sadiq',
last_name: 'Khan',
gender: 'Male',
age: 12,
address: '3235 High Forest, Glen Campbell, MS, 39035-6845, US, (601) 638-8186',
mood: "Happy",
country: {
name: 'Ireland',
code: 'IE'
}
}, {
first_name: 'Jerry',
last_name: 'Mane',
gender: 'Male',
age: 12,
address: '2234 Sleepy Pony Mall , Drain, DC, 20078-4243, US, (202) 948-3634',
mood: "Happy",
country: {
name: 'Ireland',
code: 'IE'
}
}];
// double the array twice, make more data!
students.forEach(function(item) {
students.push(cloneObject(item));
});
students.forEach(function(item) {
students.push(cloneObject(item));
});
students.forEach(function(item) {
students.push(cloneObject(item));
});
function cloneObject(obj) {
return JSON.parse(JSON.stringify(obj));
}
var columnDefs = [{
field: "first_name",
headerName: "First Name",
width: 120,
editable: true
},
{
field: "last_name",
headerName: "Last Name",
width: 120,
editable: true
},
{
field: "gender",
width: 100,
editable: true,
cellRenderer: 'genderCellRenderer',
cellEditor: 'agRichSelectCellEditor',
cellEditorParams: {
cellRenderer: 'genderCellRenderer',
values: ['Male', 'Female']
}
},
{
field: "age",
width: 80,
editable: true,
cellEditor: 'numericCellEditor'
},
{
field: "mood",
width: 100,
cellRenderer: 'moodCellRenderer',
cellEditor: 'moodEditor',
editable: true
},
{
field: "country",
width: 110,
cellRenderer: 'countryCellRenderer',
cellEditor: 'agRichSelectCellEditor',
keyCreator: function(country) {
return country.name;
},
cellEditorParams: {
cellRenderer: 'countryCellRenderer',
values: [{
name: 'Ireland',
code: 'IE'
},
{
name: 'UK',
code: 'UK'
},
{
name: 'France',
code: 'FR'
}
]
},
editable: true
},
{
field: "address",
editable: true,
cellEditor: 'agLargeTextCellEditor',
cellEditorParams: {
maxLength: '300', // override the editor defaults
cols: '50',
rows: '6'
}
}
];
var gridOptions = {
columnDefs: columnDefs,
rowData: students,
defaultColDef: {
editable: true,
sortable: true,
flex: 1,
minWidth: 100,
filter: true,
resizable: true
},
onRowEditingStarted: function(event) {
console.log('never called - not doing row editing');
},
onRowEditingStopped: function(event) {
console.log('never called - not doing row editing');
},
onCellEditingStarted: function(event) {
console.log('cellEditingStarted');
},
onCellEditingStopped: function(event) {
console.log('cellEditingStopped');
},
components: {
genderCellRenderer: GenderCellRenderer,
numericCellEditor: NumericCellEditor,
moodCellRenderer: MoodCellRenderer,
moodEditor: MoodEditor,
countryCellRenderer: CountryCellRenderer
}
};
function getCharCodeFromEvent(event) {
event = event || window.event;
return (typeof event.which == "undefined") ? event.keyCode : event.which;
}
function isCharNumeric(charStr) {
return !!/\d/.test(charStr);
}
function isKeyPressedNumeric(event) {
var charCode = getCharCodeFromEvent(event);
var charStr = String.fromCharCode(charCode);
return isCharNumeric(charStr);
}
// simple function cellRenderer, just returns back the name of the country
function CountryCellRenderer(params) {
return params.value.name;
}
// function to act as a class
function NumericCellEditor() {}
// gets called once before the renderer is used
NumericCellEditor.prototype.init = function(params) {
// create the cell
this.eInput = document.createElement('input');
if (isCharNumeric(params.charPress)) {
this.eInput.value = params.charPress;
} else {
if (params.value !== undefined && params.value !== null) {
this.eInput.value = params.value;
}
}
var that = this;
this.eInput.addEventListener('keypress', function(event) {
if (!isKeyPressedNumeric(event)) {
that.eInput.focus();
if (event.preventDefault) event.preventDefault();
} else if (that.isKeyPressedNavigation(event)) {
event.stopPropagation();
}
});
// only start edit if key pressed is a number, not a letter
var charPressIsNotANumber = params.charPress && ('1234567890'.indexOf(params.charPress) < 0);
this.cancelBeforeStart = charPressIsNotANumber;
};
NumericCellEditor.prototype.isKeyPressedNavigation = function(event) {
return event.keyCode === 39 ||
event.keyCode === 37;
};
// gets called once when grid ready to insert the element
NumericCellEditor.prototype.getGui = function() {
return this.eInput;
};
// focus and select can be done after the gui is attached
NumericCellEditor.prototype.afterGuiAttached = function() {
this.eInput.focus();
};
// returns the new value after editing
NumericCellEditor.prototype.isCancelBeforeStart = function() {
return this.cancelBeforeStart;
};
// example - will reject the number if it contains the value 007
// - not very practical, but demonstrates the method.
NumericCellEditor.prototype.isCancelAfterEnd = function() {
var value = this.getValue();
return value.indexOf('007') >= 0;
};
// returns the new value after editing
NumericCellEditor.prototype.getValue = function() {
return this.eInput.value;
};
// any cleanup we need to be done here
NumericCellEditor.prototype.destroy = function() {
// but this example is simple, no cleanup, we could even leave this method out as it's optional
};
// if true, then this editor will appear in a popup
NumericCellEditor.prototype.isPopup = function() {
// and we could leave this method out also, false is the default
return false;
};
function GenderCellRenderer() {}
GenderCellRenderer.prototype.init = function(params) {
this.eGui = document.createElement('span');
if (params.value !== "" || params.value !== undefined || params.value !== null) {
var gender = '<img border="0" width="15" height="10" src="https://raw.githubusercontent.com/ag-grid/ag-grid/master/grid-packages/ag-grid-docs/src/images/' + params.value.toLowerCase() + '.png">';
this.eGui.innerHTML = gender + ' ' + params.value;
}
};
GenderCellRenderer.prototype.getGui = function() {
return this.eGui;
};
function MoodCellRenderer() {}
MoodCellRenderer.prototype.init = function(params) {
this.eGui = document.createElement('span');
if (params.value !== "" || params.value !== undefined || params.value !== null) {
var imgForMood = params.value === 'Happy' ? 'https://raw.githubusercontent.com/ag-grid/ag-grid/master/grid-packages/ag-grid-docs/src/images/smiley.png' : 'https://raw.githubusercontent.com/ag-grid/ag-grid/master/grid-packages/ag-grid-docs/src/images/smiley-sad.png';
this.eGui.innerHTML = '<img width="20px" src="' + imgForMood + '" />';
}
};
MoodCellRenderer.prototype.getGui = function() {
return this.eGui;
};
function MoodEditor() {
this.defaultImgStyle = 'padding-left:10px; padding-right:10px; border: 1px solid transparent; padding: 4px;';
this.selectedImgStyle = 'padding-left:10px; padding-right:10px; border: 1px solid lightgreen; padding: 4px;';
}
MoodEditor.prototype.onKeyDown = function(event) {
var key = event.which || event.keyCode;
if (key == 37 || // left
key == 39) { // right
this.toggleMood();
event.stopPropagation();
}
};
MoodEditor.prototype.toggleMood = function() {
this.selectMood(this.mood === 'Happy' ? 'Sad' : 'Happy');
};
MoodEditor.prototype.init = function(params) {
this.container = document.createElement('div');
this.container.style = "border-radius: 15px; border: 1px solid grey;background: #e6e6e6;padding: 15px; text-align:center;display:inline-block;outline:none";
this.container.tabIndex = "0"; // to allow the div to capture keypresses
this.happyImg = document.createElement('img');
this.happyImg.src = 'https://raw.githubusercontent.com/ag-grid/ag-grid/master/grid-packages/ag-grid-docs/src/images/smiley.png';
this.happyImg.style = this.defaultImgStyle;
this.sadImg = document.createElement('img');
this.sadImg.src = 'https://raw.githubusercontent.com/ag-grid/ag-grid/master/grid-packages/ag-grid-docs/src/images/smiley-sad.png';
this.sadImg.style = this.defaultImgStyle;
this.container.appendChild(this.happyImg);
this.container.appendChild(this.sadImg);
var that = this;
this.happyImg.addEventListener('click', function(event) {
that.selectMood('Happy');
params.stopEditing();
});
this.sadImg.addEventListener('click', function(event) {
that.selectMood('Sad');
params.stopEditing();
});
this.container.addEventListener('keydown', function(event) {
that.onKeyDown(event)
});
this.selectMood(params.value);
};
MoodEditor.prototype.selectMood = function(mood) {
this.mood = mood;
this.happyImg.style = (mood === 'Happy') ? this.selectedImgStyle : this.defaultImgStyle;
this.sadImg.style = (mood === 'Sad') ? this.selectedImgStyle : this.defaultImgStyle;
};
// gets called once when grid ready to insert the element
MoodEditor.prototype.getGui = function() {
return this.container;
};
MoodEditor.prototype.afterGuiAttached = function() {
this.container.focus();
};
MoodEditor.prototype.getValue = function() {
return this.mood;
};
// any cleanup we need to be done here
MoodEditor.prototype.destroy = function() {};
MoodEditor.prototype.isPopup = function() {
return true;
};
// setup the grid after the page has finished loading
document.addEventListener('DOMContentLoaded', function() {
var gridDiv = document.querySelector('#myGrid');
new agGrid.Grid(gridDiv, gridOptions);
});
.ag-rich-select-list {
width: 100%;
min-width: 200px;
height: auto !important;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script>
var __basePath = './';
</script>
<style media="only screen">
html,
body {
height: 100%;
width: 100%;
margin: 0;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
}
html {
position: absolute;
top: 0;
left: 0;
padding: 0;
overflow: auto;
}
body {
padding: 1rem;
overflow: auto;
}
</style>
<script src="https://unpkg.com/#ag-grid-enterprise/all-modules#24.1.0/dist/ag-grid-enterprise.min.js"></script>
</head>
<body>
<div id="myGrid" style="height: 100%;" class="ag-theme-alpine"></div>
</body>
</html>
Related
Custom tooltip title based on dictionary mapping of values
MWE: See a graph below with countries in the x-axis. What is the best way to show the whole name in the tooltip instead of the acronym? (Show "Germany" instead of "GER", France instead of "FRA", etc.). I have like 10 or 15 of those. SEE FULL CODE IN jsfiddle var example2 = [229, 113, 109]; var labels2 = ["GER", "FRA", "LT"]; https://jsfiddle.net/user3507584/6zpb715x/6/
You can add an object with translations where the key is the value from the label and the value is the full country name: var example2 = [229, 113, 109]; var labels2 = ["GER", "FRA", "LT"]; var translations = { GER: 'Germany', FRA: 'France', LT: "Italy" } var barChartData2 = { labels: labels2, datasets: [{ label: 'Student Count', backgroundColor: '#ccece6', data: example2 }] }; function drawChart(el, data, title) { var ctx = document.getElementById(el).getContext("2d"); var bar = new Chart(ctx, { type: 'bar', data: data, options: { // Elements options apply to all of the options unless overridden in a dataset // In this case, we are setting the border of each bar to be 2px wide and green elements: { rectangle: { borderWidth: 2, borderColor: '#98c4f9', borderSkipped: 'bottom' } }, responsive: true, legend: { position: 'bottom', }, title: { display: true, text: title }, scales: { yAxes: [{ ticks: { beginAtZero: 0, min: 0 } }], xAxes: [{ ticks: { // Show all labels autoSkip: false, callback: function(tick) { var characterLimit = 20; if (tick.length >= characterLimit) { return tick.slice(0, tick.length).substring(0, characterLimit - 1).trim() + '...';; } return tick; } } }] }, tooltips: { callbacks: { title: function(tooltipItem) { return translations[tooltipItem[0].xLabel]; } } } } }); console.log(bar); }; drawChart('canvas0', barChartData2, 'example title'); <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.2.2/Chart.js"></script> <div id="container"> <canvas id="canvas0"></canvas> </div>
Highmaps mappies with drilldown
I need to do a drilldown of mappies, from country to states: https://www.highcharts.com/maps/demo/map-pies Actually I am using a custom map from Peru, but already with the example of USA would help me a lot showing me some solution. Is it possible to do this?
I've made an example with mappie and drilldown to show you how to start and achieve it. I've added drilldown for California so only this state will work. Add drilldown module: https://code.highcharts.com/maps/modules/drilldown.js Each point should have a drilldown property set. You can add it to a point object or to data array (then keys array in series should point to it. API: https://api.highcharts.com/highmaps/plotOptions.series.keys) When drilldown event occurs hide or remove each mappie series and create it again on drillup event. Code: // New map-pie series type that also allows lat/lon as center option. // Also adds a sizeFormatter option to the series, to allow dynamic sizing // of the pies. Highcharts.seriesType('mappie', 'pie', { center: null, // Can't be array by default anymore clip: true, // For map navigation states: { hover: { halo: { size: 5 } } }, dataLabels: { enabled: false } }, { getCenter: function() { var options = this.options, chart = this.chart, slicingRoom = 2 * (options.slicedOffset || 0); if (!options.center) { options.center = [null, null]; // Do the default here instead } // Handle lat/lon support if (options.center.lat !== undefined) { var point = chart.fromLatLonToPoint(options.center); options.center = [ chart.xAxis[0].toPixels(point.x, true), chart.yAxis[0].toPixels(point.y, true) ]; } // Handle dynamic size if (options.sizeFormatter) { options.size = options.sizeFormatter.call(this); } // Call parent function var result = Highcharts.seriesTypes.pie.prototype.getCenter.call(this); // Must correct for slicing room to get exact pixel pos result[0] -= slicingRoom; result[1] -= slicingRoom; return result; }, translate: function(p) { this.options.center = this.userOptions.center; this.center = this.getCenter(); return Highcharts.seriesTypes.pie.prototype.translate.call(this, p); } }); var data = [ // state, demVotes, repVotes, libVotes, grnVotes, sumVotes, winner, offset config for pies ['Alabama', 729547, 1318255, 44467, 9391, 2101660, -1], ['Alaska', 116454, 163387, 18725, 5735, 304301, -1], ['Arizona', 1161167, 1252401, 106327, 34345, 2554240, -1], ['Arkansas', 380494, 684782, 29829, 9473, 1104578, -1], ['California', 8577206, 4390272, 467370, 271047, 13705895, 1, { lon: -1, drawConnector: false }, 'us-ca'], ['Colorado', 1338870, 1202484, 144121, 38437, 2723912, 1], ['Connecticut', 897572, 673215, 48676, 22841, 1642304, 1, { lat: -1.5, lon: 1 }], ['Delaware', 235603, 185127, 14757, 6103, 441590, 1, { lat: -1.3, lon: 2 }], ['District of Columbia', 282830, 12723, 4906, 4258, 304717, 1, { lat: -2, lon: 2 }], ['Florida', 4504975, 4617886, 207043, 64399, 9394303, -1], ['Georgia', 1877963, 2089104, 125306, 0, 4092373, -1], ['Hawaii', 266891, 128847, 15954, 12737, 424429, 1, { lat: -0.5, lon: 0.5, drawConnector: false }], ['Idaho', 189765, 409055, 28331, 8496, 635647, -1], ['Illinois', 2977498, 2118179, 208682, 74112, 5378471, 1], ['Indiana', 1039126, 1557286, 133993, 7841, 2738246, -1], ['Iowa', 653669, 800983, 59186, 11479, 1525317, -1], ['Kansas', 427005, 671018, 55406, 23506, 1176935, -1], ['Kentucky', 628854, 1202971, 53752, 13913, 1899490, -1], ['Louisiana', 780154, 1178638, 37978, 14031, 2010801, -1], ['Maine', 352156, 332418, 37578, 13995, 736147, 1], ['Maryland', 1502820, 878615, 78225, 33380, 2493040, 1, { lon: 0.6, drawConnector: false }], ['Massachusetts', 1995196, 1090893, 138018, 47661, 3271768, 1, { lon: 3 }], ['Michigan', 2268839, 2279543, 172136, 51463, 4771981, -1], ['Minnesota', 1367716, 1322951, 112972, 36985, 2840624, 1, { lon: -1, drawConnector: false }], ['Mississippi', 462127, 678284, 14411, 3595, 1158417, -1], ['Missouri', 1054889, 1585753, 96404, 25086, 2762132, -1], ['Montana', 174281, 273879, 28036, 7868, 484064, -1], ['Nebraska', 273185, 485372, 38746, 8337, 805640, -1], ['Nevada', 539260, 512058, 37384, 0, 1088702, 1], ['New Hampshire', 348526, 345790, 30694, 6465, 731475, 1], ['New Jersey', 1967444, 1509688, 72143, 37131, 3586406, 1, { lat: -1, lon: 1.2 }], ['New Mexico', 380923, 316134, 74544, 9797, 781398, 1], ['New York', 4145376, 2638135, 162273, 100110, 7045894, 1], ['North Carolina', 2169496, 2345235, 130021, 1038, 4645790, -1], ['North Dakota', 93758, 216794, 21434, 378, 332364, -1], ['Ohio', 2320596, 2776683, 174266, 44310, 5315855, -1], ['Oklahoma', 420375, 949136, 83481, 0, 1452992, -1], ['Oregon', 991580, 774080, 93875, 49247, 1908782, 1], ['Pennsylvania', 2874136, 2945302, 144826, 49334, 6013598, -1], ['Rhode Island', 227062, 166454, 14700, 6171, 414387, 1, { lat: -0.7, lon: 1.7 }], ['South Carolina', 855373, 1155389, 49204, 13034, 2073000, -1], ['South Dakota', 117442, 227701, 20845, 0, 365988, -1], ['Tennessee', 868853, 1519926, 70286, 15952, 2475017, -1], ['Texas', 3877868, 4685047, 283492, 71558, 8917965, -1], ['Utah', 222858, 375006, 39608, 7695, 645167, -1], ['Vermont', 178573, 95369, 10078, 6758, 290778, 1, { lat: 2 }], ['Virginia', 1981473, 1769443, 118274, 27638, 3896828, 1], ['Washington', 1727840, 1210370, 160356, 57571, 3156137, 1], ['West Virginia', 187519, 486304, 22958, 8016, 704797, -1], ['Wisconsin', 1382947, 1407028, 106470, 31016, 2927461, -1], ['Wyoming', 55973, 174419, 13287, 2515, 246194, -1] ], maxVotes = 0, demColor = 'rgba(74,131,240,0.80)', repColor = 'rgba(220,71,71,0.80)', libColor = 'rgba(240,190,50,0.80)', grnColor = 'rgba(90,200,90,0.80)'; // Compute max votes to find relative sizes of bubbles Highcharts.each(data, function(row) { maxVotes = Math.max(maxVotes, row[5]); }); // Build the chart var chart = Highcharts.mapChart('container', { chart: { animation: false, // Disable animation, especially for zooming events: { load: function() { addMapPie(this); }, drilldown: function(e) { if (!e.seriesOptions) { var chart = this, mapKey = 'countries/us/' + e.point.drilldown + '-all', // Handle error, the timeout is cleared on success fail = setTimeout(function() { if (!Highcharts.maps[mapKey]) { chart.showLoading('<i class="icon-frown"></i> Failed loading ' + e.point.name); fail = setTimeout(function() { chart.hideLoading(); }, 1000); } }, 3000); // Show the spinner chart.showLoading('<i class="icon-spinner icon-spin icon-3x"></i>'); // Font Awesome spinner // Load the drilldown map $.getScript('https://code.highcharts.com/mapdata/' + mapKey + '.js', function() { data = Highcharts.geojson(Highcharts.maps[mapKey]); // Set a non-random bogus value $.each(data, function(i) { this.value = i; }); chart.series.forEach(function(s) { if (s.options.type === 'mappie') { s.hide(); } }); // Hide loading and add series chart.hideLoading(); clearTimeout(fail); chart.addSeriesAsDrilldown(e.point, { name: e.point.name, data: data, dataLabels: { enabled: true, format: '{point.name}' } }); }); } this.setTitle(null, { text: e.point.name }); }, drillup: function() { this.setTitle(null, { text: '' }); this.series.forEach(function(s) { if (s.options.type === 'mappie') { s.show(); } }); } } }, title: { text: 'USA 2016 Presidential Election Results' }, colorAxis: { dataClasses: [{ from: -1, to: 0, color: 'rgba(244,91,91,0.5)', name: 'Republican' }, { from: 0, to: 1, color: 'rgba(124,181,236,0.5)', name: 'Democrat' }, { from: 2, to: 3, name: 'Libertarian', color: libColor }, { from: 3, to: 4, name: 'Green', color: grnColor }] }, mapNavigation: { enabled: true }, // Limit zoom range yAxis: { minRange: 2300 }, tooltip: { useHTML: true }, // Default options for the pies plotOptions: { mappie: { borderColor: 'rgba(255,255,255,0.4)', borderWidth: 1, tooltip: { headerFormat: '' } } }, series: [{ mapData: Highcharts.maps['countries/us/us-all'], data: data, name: 'States', borderColor: '#FFF', showInLegend: false, joinBy: ['name', 'id'], keys: ['id', 'demVotes', 'repVotes', 'libVotes', 'grnVotes', 'sumVotes', 'value', 'pieOffset', 'drilldown' ], tooltip: { headerFormat: '', pointFormatter: function() { var hoverVotes = this.hoverVotes; // Used by pie only return '<b>' + this.id + ' votes</b><br/>' + Highcharts.map([ ['Democrats', this.demVotes, demColor], ['Republicans', this.repVotes, repColor], ['Libertarians', this.libVotes, libColor], ['Green', this.grnVotes, grnColor] ].sort(function(a, b) { return b[1] - a[1]; // Sort tooltip by most votes }), function(line) { return '<span style="color:' + line[2] + // Colorized bullet '">\u25CF</span> ' + // Party and votes (line[0] === hoverVotes ? '<b>' : '') + line[0] + ': ' + Highcharts.numberFormat(line[1], 0) + (line[0] === hoverVotes ? '</b>' : '') + '<br/>'; }).join('') + '<hr/>Total: ' + Highcharts.numberFormat(this.sumVotes, 0); } } }, { name: 'Separators', type: 'mapline', data: Highcharts.geojson(Highcharts.maps['countries/us/us-all'], 'mapline'), color: '#707070', showInLegend: false, enableMouseTracking: false }, { name: 'Connectors', type: 'mapline', color: 'rgba(130, 130, 130, 0.5)', zIndex: 5, showInLegend: false, enableMouseTracking: false }], drilldown: { activeDataLabelStyle: { color: '#FFFFFF', textDecoration: 'none', textOutline: '1px #000000' }, drillUpButton: { relativeTo: 'spacingBox', position: { x: 0, y: 60 } } } }); function addMapPie(chart) { // Add the pies after chart load, optionally with offset and connectors Highcharts.each(chart.series[0].points, function(state) { if (!state.id) { return; // Skip points with no data, if any } var pieOffset = state.pieOffset || {}, centerLat = parseFloat(state.properties.latitude), centerLon = parseFloat(state.properties.longitude); // Add the pie for this state chart.addSeries({ type: 'mappie', name: state.id, zIndex: 6, // Keep pies above connector lines sizeFormatter: function() { var yAxis = this.chart.yAxis[0], zoomFactor = (yAxis.dataMax - yAxis.dataMin) / (yAxis.max - yAxis.min); return Math.max( this.chart.chartWidth / 45 * zoomFactor, // Min size this.chart.chartWidth / 11 * zoomFactor * state.sumVotes / maxVotes ); }, tooltip: { // Use the state tooltip for the pies as well pointFormatter: function() { return state.series.tooltipOptions.pointFormatter.call({ id: state.id, hoverVotes: this.name, demVotes: state.demVotes, repVotes: state.repVotes, libVotes: state.libVotes, grnVotes: state.grnVotes, sumVotes: state.sumVotes }); } }, data: [{ name: 'Democrats', y: state.demVotes, color: demColor }, { name: 'Republicans', y: state.repVotes, color: repColor }, { name: 'Libertarians', y: state.libVotes, color: libColor }, { name: 'Green', y: state.grnVotes, color: grnColor }], center: { lat: centerLat + (pieOffset.lat || 0), lon: centerLon + (pieOffset.lon || 0) } }, false); // Draw connector to state center if the pie has been offset if (pieOffset.drawConnector !== false) { var centerPoint = chart.fromLatLonToPoint({ lat: centerLat, lon: centerLon }), offsetPoint = chart.fromLatLonToPoint({ lat: centerLat + (pieOffset.lat || 0), lon: centerLon + (pieOffset.lon || 0) }); chart.series[2].addPoint({ name: state.id, path: 'M' + offsetPoint.x + ' ' + offsetPoint.y + 'L' + centerPoint.x + ' ' + centerPoint.y }, false); } }); // Only redraw once all pies and connectors have been added chart.redraw(); } #container { min-width: 320px; max-width: 800px; height: 500px; margin: 1em auto; } <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.3.15/proj4.js"></script> <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> <script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/maps/modules/map.js"></script> <script src="https://code.highcharts.com/maps/modules/data.js"></script> <script src="https://code.highcharts.com/maps/modules/drilldown.js"></script> <script src="https://code.highcharts.com/maps/modules/exporting.js"></script> <script src="https://code.highcharts.com/maps/modules/offline-exporting.js"></script> <script src="https://code.highcharts.com/mapdata/countries/us/us-all.js"></script> <link href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet"> <div id="container"></div> Demo: https://jsfiddle.net/BlackLabel/1d845opk/1/ EDIT To add mappies also to the first level of drilldown you have to remove mappies series form the main view of the map when drilldown event occurs and create new ones for drilled data. It's quite difficult to explain exactly how to make it, so I prepared an example where each drilled level has sample data (you can get them from a server the same as drilled map data). I hope this example will help and you will see what's going on there. Demo: http://jsfiddle.net/BlackLabel/zLcnby79/
Thank you Wojciech Chmiel ! I did my map with the help of your post. // New map-pie series type that also allows lat/lon as center option. // Also adds a sizeFormatter option to the series, to allow dynamic sizing // of the pies. Highcharts.seriesType('mappie', 'pie', { center: null, // Can't be array by default anymore clip: true, // For map navigation states: { hover: { halo: { size: 5 } } }, dataLabels: { enabled: false } }, { getCenter: function() { var options = this.options, chart = this.chart, slicingRoom = 2 * (options.slicedOffset || 0); if (!options.center) { options.center = [null, null]; // Do the default here instead } // Replace lat/lon with plotX/plotY if (options.center.plotX !== undefined) { options.center = [options.center.plotX, options.center.plotY]; } // Handle dynamic size if (options.sizeFormatter) { options.size = options.sizeFormatter.call(this); } // Call parent function var result = Highcharts.seriesTypes.pie.prototype.getCenter.call(this); // Must correct for slicing room to get exact pixel pos result[0] -= slicingRoom; result[1] -= slicingRoom; return result; }, translate: function (p) { this.options.center = this.userOptions.center; this.center = this.getCenter(); return Highcharts.seriesTypes.pie.prototype.translate.call(this, p); } }); var data = [ // state, demVotes, repVotes, libVotes, grnVotes, sumVotes, winner, drilldown ['CAPLINA-OCONA', 729547, 1318255, 44467, 9391, 2101660, -1, 'aaa01'], ['CHAPARRA-CHINCHA', 116454, 163387, 18725, 5735, 304301, -1, 'aaa02'], ['CANETE-FORTALEZA', 1161167, 1252401, 106327, 34345, 2554240, -1, 'aaa03'], ['HUARMEY-CHICAMA', 380494, 684782, 29829, 9473, 1104578, -1, 'aaa04'], ['JEQUETEPEQUE-ZARUMILLA', 8577206, 4390272, 467370, 271047, 13705895, 1, 'aaa05'], ['MARANON', 1338870, 1202484, 144121, 38437, 2723912, 1, 'aaa06'], ['AMAZONAS', 897572, 673215, 48676, 22841, 1642304, 1, 'aaa07'], ['HUALLAGA', 235603, 185127, 14757, 6103, 441590, 1, 'aaa08'], ['UCAYALI', 282830, 12723, 4906, 4258, 304717, 1, 'aaa09'], ['MANTARO', 4504975, 4617886, 207043, 64399, 9394303, -1, 'aaa10'], ['PAMPAS-APURIMAC', 1877963, 2089104, 125306, 0, 4092373, -1, 'aaa11'], ['URUBAMBA-VILCANOTA', 266891, 128847, 15954, 12737, 424429, 1, 'aaa12'], ['MADRE DE DIOS', 189765, 409055, 28331, 8496, 635647, -1, 'aaa13'], ['TITICACA', 2977498, 2118179, 208682, 74112, 5378471, 1, 'aaa14'] ], maxVotes = 0, demColor = 'rgba(74,131,240,0.80)', repColor = 'rgba(220,71,71,0.80)', libColor = 'rgba(240,190,50,0.80)', grnColor = 'rgba(90,200,90,0.80)'; // Compute max votes to find relative sizes of bubbles Highcharts.each(data, function(row) { maxVotes = Math.max(maxVotes, row[5]); }); // Build the chart var chart = Highcharts.mapChart('container', { chart: { animation: false, // Disable animation, especially for zooming events: { load: function() { addMapPie(this); }, drilldown: function(e) { if (!e.seriesOptions) { var chart = this, //mapKey = 'countries/us/' + e.point.drilldown + '-all', mapKey = 'paises/pe/' + e.point.drilldown, ruta = e.point.drilldown, // Handle error, the timeout is cleared on success fail = setTimeout(function() { if (!Highcharts.maps[mapKey]) { chart.showLoading('<i class="icon-frown"></i> Failed loading ' + e.point.name); fail = setTimeout(function() { chart.hideLoading(); }, 1000); } }, 3000); // Show the spinner chart.showLoading('<i class="icon-spinner icon-spin icon-3x"></i>'); // Font Awesome spinner // Load the drilldown map //$.getScript('https://code.highcharts.com/mapdata/' + mapKey + '.js', function() { //$.getScript('http://test1.ana.gob.pe/prueba-mappies/' + ruta + '.js', function () { $.getScript('https://aplicaciones01.ana.gob.pe/mappies/' + ruta + '.js', function () { data = Highcharts.geojson(Highcharts.maps[mapKey]); // Set a non-random bogus value $.each(data, function(i) { this.value = i; }); chart.series.forEach(function(s) { if (s.options.type === 'mappie') { s.hide(); } }); // Hide loading and add series chart.hideLoading(); clearTimeout(fail); chart.addSeriesAsDrilldown(e.point, { name: e.point.name, data: data, dataLabels: { enabled: true, format: '{point.name}' } }); }); } this.setTitle(null, { text: e.point.name }); }, drillup: function() { this.setTitle(null, { text: '' }); this.series.forEach(function(s) { if (s.options.type === 'mappie') { s.show(); } }); } } }, title: { text: 'Resultados' }, colorAxis: { dataClasses: [{ from: -1, to: 0, color: 'rgba(244,91,91,0.5)', name: 'Republican' }, { from: 0, to: 1, color: 'rgba(124,181,236,0.5)', name: 'Democrat' }, { from: 2, to: 3, name: 'Libertarian', color: libColor }, { from: 3, to: 4, name: 'Green', color: grnColor }] }, mapNavigation: { enabled: true //Para el zoom (+ -) }, // Limit zoom range yAxis: { minRange: 2300 }, tooltip: { useHTML: true }, // Default options for the pies plotOptions: { mappie: { borderColor: 'rgba(255,255,255,0.4)', borderWidth: 1, tooltip: { headerFormat: '' } } }, series: [{ mapData: Highcharts.maps['paises/pe/aaa-all'], data: data, name: 'States', borderColor: '#FFF', showInLegend: false, joinBy: ['name', 'id'], //keys: ['id', 'demVotes', 'repVotes', 'libVotes', 'grnVotes', // 'sumVotes', 'value', 'pieOffset'], keys: ['id', 'demVotes', 'repVotes', 'libVotes', 'grnVotes', 'sumVotes', 'value', 'drilldown'], tooltip: { headerFormat: '', pointFormatter: function () { var hoverVotes = this.hoverVotes; // Used by pie only return '<b>' + this.id + ' votes</b><br/>' + Highcharts.map([ ['Democrats', this.demVotes, demColor], ['Republicans', this.repVotes, repColor], ['Libertarians', this.libVotes, libColor], ['Green', this.grnVotes, grnColor] ].sort(function (a, b) { return b[1] - a[1]; // Sort tooltip by most votes }), function (line) { return '<span style="color:' + line[2] + // Colorized bullet '">\u25CF</span> ' + // Party and votes (line[0] === hoverVotes ? '<b>' : '') + line[0] + ': ' + Highcharts.numberFormat(line[1], 0) + (line[0] === hoverVotes ? '</b>' : '') + '<br/>'; }).join('') + '<hr/>Total: ' + Highcharts.numberFormat(this.sumVotes, 0); } } }], drilldown: { activeDataLabelStyle: { color: '#FFFFFF', textDecoration: 'none', textOutline: '1px #000000' }, drillUpButton: { relativeTo: 'spacingBox', position: { x: 0, y: 60 } } } }); function addMapPie(chart) { // Add the pies after chart load, optionally with offset and connectors Highcharts.each(chart.series[0].points, function(state) { //if (!state.id) { if (!state.id || !state.properties) { return; // Skip points with no data, if any } var pieOffset = state.pieOffset || {}, centerLat = parseFloat(state.properties.latitude), centerLon = parseFloat(state.properties.longitude); // Add the pie for this state chart.addSeries({ type: 'mappie', name: state.id, zIndex: 6, // Keep pies above connector lines sizeFormatter: function () { var yAxis = this.chart.yAxis[0], zoomFactor = (yAxis.dataMax - yAxis.dataMin) / (yAxis.max - yAxis.min); return Math.max( this.chart.chartWidth / 45 * zoomFactor, // Min size this.chart.chartWidth / 11 * zoomFactor * state.sumVotes / maxVotes ); }, /*****/ tooltip: { // Use the state tooltip for the pies as well pointFormatter: function () { return state.series.tooltipOptions.pointFormatter.call({ id: state.id, hoverVotes: this.name, demVotes: state.demVotes, repVotes: state.repVotes, libVotes: state.libVotes, grnVotes: state.grnVotes, sumVotes: state.sumVotes }); } }, data: [{ name: 'Democrats', y: state.demVotes, color: demColor }, { name: 'Republicans', y: state.repVotes, color: repColor }, { name: 'Libertarians', y: state.libVotes, color: libColor }, { name: 'Green', y: state.grnVotes, color: grnColor }], center: { /*lat: centerLat + (pieOffset.lat || 0), lon: centerLon + (pieOffset.lon || 0)*/ plotX: state.plotX, plotY: state.plotY } }, false); }); // Only redraw once all pies and connectors have been added chart.redraw(); } #container { min-width: 320px; max-width: 800px; height: 500px; margin: 1em auto; } <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.3.15/proj4.js"></script> <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> <script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/maps/modules/map.js"></script> <script src="https://code.highcharts.com/modules/data.js"></script> <script src="https://code.highcharts.com/modules/drilldown.js"></script> <script src="https://code.highcharts.com/maps/modules/exporting.js"></script> <script src="https://code.highcharts.com/maps/modules/offline-exporting.js"></script> <script src="https://aplicaciones01.ana.gob.pe/mappies/AAA_psad56_simp.js"></script> <link href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet"> <div id="container"></div> Here: - https://jsfiddle.net/JMarcia/w06k5zog/17/
Accessing state with Ag-grid
Probably not a Ag-Grid problem but I'm stuck on this one for some time. Having a component in react like this : export default class Recrutement extends React.Component { constructor(props) { super(props); this.state = { candidats: [], // We suppose here that values are filled values: [] // We suppose here that values are filled }; this.getContacts(); this.getValues(); } columnDefs = [{ cellRenderer: function(params) { return '<span><i class="material-icons"></i></span>'; }, suppressMovable: true, width: 100, colId: 1, //width: (self.columnDefinitions.find(function (v) { return v.colId === 1 }) || {}).size || 50, pinned: 'left', suppressFilter: true }, { width: 100, headerName: "Formation", editable: true, colId: 7, suppressMovable: true, //width : (self.columnDefinitions.find(function (v) { return v.colId === 7 }) || {}).size || null, autoHeight: true, cellEditor: 'agSelectCellEditor', valueGetter: function(params) { if (params.data.candidat.formationId === null) return ""; return this.state.values.formations.find(function(val) { return val.id === params.data.candidat.formationId; }).name; }, valueSetter: function(params) { return selectValueSetter(this.state.values.formations, true, 'formationId', params); }, cellEditorParams: function() { return { values: this.state.values.formations .sort(function(a, b) { if (a.name < b.name) return -1; if (a.name > b.name) return 1; return 0; }) .map(function(v) { return v.name; }) }; }, filter: "anyOfWordsFilter" }, ]; <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> What I want is that valueGetter for example have access to this.state. However here, I just get everytime : Uncaught TypeError: Cannot read property 'state' of undefined I tried the bind system (or maybe I did it wrong, probably :D), the arrow one however none of them are working. How can I access the state in this condition ? To use Ag-grid, I need my array to stay like this (function can change)
replace valueSetter: function(params) { return selectValueSetter(this.state.values.formations, true, 'formationId', params); }, by valueSetter: (params) => { return selectValueSetter(this.state.values.formations, true, 'formationId', params); }, and please ready this post and this one
Highcharts :Donut chart overlaps data labels
I'm working on a donut chart type, with the Highcharts library. As you can see in the image below, some of the inner data labels are overlapped. I've been playing with the parameter "distance" but doesn't fix this. Find attached the code below, // Create the chart $(container).highcharts({ chart: { type: 'pie' }, credits: { enabled: false }, exporting: { buttons: { contextButton: { symbol: 'url(/icon-turn-down.png)' } } }, title: { text: _title, margin: 50 }, plotOptions: { pie: { shadow: false, center: ['50%', '50%'] } }, tooltip: { formatter: function() { var s = this.point.name.split('.'); if (s.length == 1) { return this.y > 1? '<b>'+this.point.name+':</b> '+Highcharts.numberFormat(this.point.y) : null; } return this.y > 1? s[0]+'<br /><b>'+$.trim(s[1])+':</b> '+Highcharts.numberFormat(this.point.y) : null; } }, series: [{ name: '', data: innerData, size: '80%', dataLabels: { formatter: function() { return this.y > 0 ? this.point.name : null; }, color: 'white', distance: -50 } }, { name: '', data: outerData, size: '100%', innerSize: '80%', dataLabels: { formatter: function() { var s = this.point.name.split('.'); if (s.length == 1) { return this.y > 1 ? '<b>'+ this.point.name+':</b> '+ Highcharts.numberFormat(this.point.y) : null ; } s = this.point.name.substring(this.point.name.indexOf(".")+2); return this.y > 1 ? '<b>'+ s+':</b> '+ Highcharts.numberFormat(this.point.y): null; }, style: { fontSize: "10px", fontColor: "#000000" } } }] });
Finally, I found a solution, which is playing with the "startangle" attribute. series: [{ name: '', data: innerData, startAngle:110, size: '80%', dataLabels: { formatter: function() { return this.y > 0 ? this.point.name : null; }, color: 'white', distance: -45 }, { ...
Distance parameter cannot be applied for each point, only general, so only what comes to my mind is iteared on each datalabel and use translate() function, or use formatter, apply CSS class and dhten use top/left parameter for each element. But will be helpful if you recreate your example as fiddle.
Extjs Cannot read property 'dom' of null
In short, I have a login panel, which will be shown when onClick event is true, but I get error Cannot read property 'dom' of null. When I click second time - the panel is shown, but some elements of it are not shown. When I click for 3th time, the other elements has show, an last, I ger error "Cannot call method 'bringToFront' of undefined". Ext.onReady(function() { Ext.QuickTips.init(); Ext.ns('Site.login'); var globalKeyMap = new Ext.KeyMap(document); globalKeyMap.accessKey = function(key, handler, scope) { var h = function(n, e) { e.preventDefault(); handler.call(scope || this, n, e); }; this.on(key, h, scope); }; var trackEnter = function(tf, e) { if (e.keyCode == 13) { e.stopPropagation(); doLogin(); } } var doLogin = function() { var f = loginPanel.getForm(); if (f.isValid()) { f.doAction(new Hypo.form.Action.DwrSubmit(f, { waitMsg: 'Authentication is in progress', invoker: function(form, cb) { Login.login(form.getValues(), cb); }, success: function(fp, o) { loginForm.hide(); Ext.getBody().addClass("x-body-masked"); var w = loginForm; w.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true)); w.mask.show(); if(o.result.data[0].authorities[0].authority=='ROLE_SUPERVISOR') { setTimeout('document.location = "AdminUsers.jsp"'); } else if(o.result.data[0].authorities[0].authority=='ROLE_ADMIN') { setTimeout('document.location = "AdminUsers.jsp"'); } else { setTimeout('document.location = "List.jsp"'); } } })); } } var loginPanel = new Ext.FormPanel({ id: 'loginPanel', labelWidth: 75, // label settings here cascade unless overridden frame: false, border: false, bodyStyle:'padding:5px 5px 0', width: 350, defaults: { width: 230 }, defaultType: 'textfield', autoHeight: true, items: [{ id: 'idxLogin', fieldLabel: 'Login', name: 'login', allowBlank: false, enableKeyEvents: true, maxLength: 50, listeners: { 'keypress': trackEnter } }, new Ext.form.TextField({ fieldLabel: 'Password', name: 'password', inputType: 'password', enableKeyEvents: true, maxLength: 50, listeners: { 'keypress': trackEnter } }) ] }); var loginForm = new Ext.Window({ layout : 'fit', width : 350, closable : false, modal: true, plain : true, title: 'User Authentication', items: loginPanel, autoHeight: true, buttons: [{ text: 'OK', handler: doLogin },{ text: 'Cancel', handler: function() { loginForm.hide(); } }], listeners: { 'activate': function() { setTimeout(function() { Ext.getCmp("idxLogin").focus(); }, 100); } } }); Site.login.window = loginForm; }); Login I tryed to add renderTo:'someDiv' and add to body a div with id "someDiv". But I received the same error message. Please, help with that.