Snippets
Created by
Piotr Szrajber
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | //# sourceURL=customization.js
/**
* Add a custom row action in the data table that zooms on particular feature
* It depends on a BI Map with
* - choropleth
* - datatable
* - one additional row chart
* 2017-09-13 Piotr Szrajber <piotr.szrajber@hexagongeospatial.com>
*/
const KEY_PROPERTY = "GEO_ID", // change to your geometry ID
BUFFER_SIZE = 100;
let GLOBALS = {},
TIMEOUT;
// waits until choropleth widget is ready
function waitForChoropleth(callback) {
gsp.bi.stage.findWidgets({
descriptors: [{
chartM: {
chart: "choropleth"
}
}]
}, function(widgets) {
if (!widgets || !widgets[0]) {
TIMEOUT = setTimeout(function() {
waitForChoropleth(callback);
}, 500);
} else {
clearTimeout(TIMEOUT);
callback(widgets[0]);
}
});
}
// waits until dc charts are filled with SVG - that means they are already initialized
// this method is not perfect as it depends on at least one chart with SVG...
// @param {Function} fn callback
function chartsReady(fn) {
let observer = new MutationObserver(function(mutations, me) {
let chartWithSvg = document.querySelector(".widget-chart.dc-chart>svg");
if (chartWithSvg) {
fn();
me.disconnect();
}
});
observer.observe(document, {
childList: true,
subtree: true
});
}
function zoomToBBox(bottomLeftCorner, topRightCorner, callback, errback) {
// transform sample points to current CRS
gsp.crs.transform({
points: [bottomLeftCorner, topRightCorner],
sourceCrsId: "EPSG:4326",
targetCrsId: gsp.crs.getCurrent()
}, function(transformationResult) {
// get BBOX in form minx, miny, maxx, maxy
var points = transformationResult.points,
bbox = [points[0].x, points[0].y, points[1].x, points[1].y];
gsp.map.zoom({
bbox: bbox
});
});
}
// zoom to feature
// note: it uses internal GVC's turf reference
function zoomToFeature(featureId) {
if (!GLOBALS.geochart) return;
let feature = GLOBALS.geochart.geoJson().features.find(function(f) {
return f.properties[KEY_PROPERTY] === featureId;
});
if (!feature) {
gsp.ui.info("This row has no associated geometry");
return;
}
gsp.bi.stage.requireLibraries(function(gvc) {
let geom = feature.geometry.type === "Point" ? gvc.turf.buffer(feature.geometry, BUFFER_SIZE) : feature.geometry;
let bbox = gvc.turf.bbox(geom);
zoomToBBox({
x: bbox[0],
y: bbox[1]
}, {
x: bbox[2],
y: bbox[3]
}, function() {
gsp.ui.info(`Successfully centered on [${bbox.join(",")}]`);
}, function() {
gsp.ui.info("Could not zoom on this feature");
});
});
}
// add custom row action zoomToFeature
function reformatTable(chart) {
let columns = chart.columns();
chart.columns(columns.concat([{
label: "Tools",
format: function(d) {
let featureId = d[KEY_PROPERTY];
if (!window.zoomToFeature) {
window.zoomToFeature = zoomToFeature;
}
return `<a href="#" onClick=window.zoomToFeature("${featureId}")>ZOOM</a>`;
}
}]));
}
// customize charts
chartsReady(function() {
gsp.bi.stage.findStage(null, function(stage) {
gsp.bi.stage.findWidgets({
descriptors: [{
chartM: {
chart: "table"
}
}]
}, function(widgets) {
let table = widgets[0];
console.log(table);
if (!table) return;
reformatTable(table.chart);
});
});
});
// lets you modify the choropleth behavior
waitForChoropleth(function(widget) {
let geochart = widget.chart;
GLOBALS.geochart = geochart;
// do other changes with the choropleth
});
|
Comments (0)
You can clone a snippet to your computer for local editing. Learn more.