OS Data Hub - Postcode from Grid Reference - postal-code

I look after the website for a walking club in SW England, which shows a list of forthcoming walks. Each walk entry has an OS Grid Reference for the start of the walk, and a UK Postcode which a walker can enter to their SatNav device, to help them drive to the start of the walk. I currently get the nearest postcode to the starting point grid reference for each walk, using the API for Nearby UK, which also gives me the compass bearing and distance from my grid reference to the centre of the postcode, which in a country area can be a mile or more from the walk start. From these I work out the grid reference at the postcode centre, and then I can show both points as markers on an OS map - so far, so good.
Having recently completed the migration from OS Open Space to OS Data Hub, I wonder if I could also use OS Data Hub to give me the nearest postcode to a grid reference, plus either bearing and distance from one to the other, or the grid reference of the postcode centre, rather than needing to use the Nearby API for this purpose.
I asked the Customer Success team at Ordnance Survey about this, about a month ago, but no help from them yet. I've also tried various ways of using the UK Postcodes Database, which lists every UK postcode with its Eastings and Northings co-ordinates, but searching through the entire list looking for the nearest co-ordinates, using Pythagoras to work out the distance to a walk starting point, takes minutes. This may be because I have to make the search using our walks database, which is written in Visual Basic, but that's another story.
Any pointers as to how to get a nearest postcode and its location from OS Data Hub, for a given grid reference, would be most welcome.

You can find the nearest postcode as long as it is centred no more than 1km away, for example
https://api.os.uk/search/names/v1/nearest?point=440200,458300&radius=1000&fq=LOCAL_TYPE:Postcode&key=yourkey
Beyond 1km you would need further searches in an outer circle around the original point
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Basic Map</title>
<link rel="stylesheet" href="https://labs.os.uk/public/os-api-branding/v0.2.0/os-api-branding.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.5.0/css/ol.css" />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id="map"></div>
<script src="https://labs.os.uk/public/os-api-branding/v0.2.0/os-api-branding.js"></script>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.5.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<script>
var apiKey = 'ufArYa1UUPHJcOYbiJDaKkA7Fb4oCkEs';
var serviceUrl = 'https://api.os.uk/maps/raster/v1/zxy';
// Setup the EPSG:27700 (British National Grid) projection.
proj4.defs("EPSG:27700", "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +no_defs");
ol.proj.proj4.register(proj4);
var tilegrid = new ol.tilegrid.TileGrid({
resolutions: [ 896.0, 448.0, 224.0, 112.0, 56.0, 28.0, 14.0, 7.0, 3.5, 1.75 ],
origin: [ -238375.0, 1376256.0 ]
});
var gridReference = new ol.Feature();
gridReference.setStyle(
new ol.style.Style({
image: new ol.style.Circle({
radius: 6,
fill: new ol.style.Fill({
color: 'red'
})
}),
text: new ol.style.Text({
font: 'bold 14px sans-serif',
offsetY: -6,
textBaseline: 'bottom'
})
})
);
var postcode = new ol.Feature();
postcode.setStyle(
new ol.style.Style({
image: new ol.style.Circle({
radius: 6,
fill: new ol.style.Fill({
color: 'blue'
})
}),
text: new ol.style.Text({
font: 'bold 14px sans-serif',
offsetY: -6,
textBaseline: 'bottom'
})
})
);
// Initialize the map object.
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.XYZ({
url: serviceUrl + '/Road_27700/{z}/{x}/{y}.png?key=' + apiKey,
projection: 'EPSG:27700',
tileGrid: tilegrid
})
}),
new ol.layer.Vector({
source: new ol.source.Vector({
features: [gridReference, postcode]
})
})
],
target: 'map',
view: new ol.View({
projection: 'EPSG:27700',
extent: [ -238375.0, 0.0, 900000.0, 1376256.0 ],
resolutions: tilegrid.getResolutions(),
minZoom: 0,
maxZoom: 9,
center: [ 337297, 503695 ],
zoom: 7
})
});
map.on('singleclick', function(evt) {
gridReference.setGeometry(new ol.geom.Point(evt.coordinate));
postcode.setGeometry(undefined);
var x = (Math.round(evt.coordinate[0]/10)/10) + 10000;
var y = (Math.round(evt.coordinate[1]/10)/10) + 5000;
var a1y = (4 - (Math.floor(y/5000)%5))*5;
var a2y = (4 - (Math.floor(y/1000)%5))*5;
var y1 = Math.floor(y/100)%10;
var y2 = Math.floor(y/10)%10;
var y3 = Math.floor(y)%10;
a1y += (Math.floor(x/5000)%5);
a2y += (Math.floor(x/1000)%5);
var x1 = Math.floor(x/100)%10;
var x2 = Math.floor(x/10)%10;
var x3 = Math.floor(x)%10;
var grid500km = String.fromCharCode(a1y + Math.floor((a1y+17)/25) + "A".charCodeAt(0));
var grid100km = grid500km + String.fromCharCode(a2y + Math.floor((a2y+17)/25) + "A".charCodeAt(0));
var gridText = grid100km + x1 + x2 + x3 + y1 + y2 + y3;
gridReference.getStyle().getText().setText(gridText);
var minDistSq = Infinity;
var postcodeCoord, postcodeText;
var radius = 0;
tryPoints([evt.coordinate]);
function tryPoints(coordinates) {
var promises = [];
coordinates.forEach(function(coordinate) {
promises.push(
fetch(
'https://api.os.uk/search/names/v1/nearest?point=' +
coordinate[0].toFixed(2) + ',' + coordinate[1].toFixed(2) +
'&radius=1000&fq=LOCAL_TYPE:Postcode&key=' + apiKey
).then(function(response) {
return response.json();
})
);
});
Promise.all(promises).then(function(results) {
results.forEach(function(result) {
if (result.results && result.results.length > 0) {
var entry = result.results[0]['GAZETTEER_ENTRY'];
var dx = entry['GEOMETRY_X'] - evt.coordinate[0];
var dy = entry['GEOMETRY_Y'] - evt.coordinate[1];
var distSq = dx * dx + dy * dy;
if (distSq < minDistSq) {
minDistSq = distSq;
postcodeCoord = [entry['GEOMETRY_X'], entry['GEOMETRY_Y']];
postcodeText = entry['NAME1'];
}
}
});
if (postcodeCoord) {
postcode.setGeometry(new ol.geom.Point(postcodeCoord));
postcode.getStyle().getText().setText(postcodeText);
} else if (radius < 4) {
radius++;
var outerCircle = ol.geom.Polygon.fromCircle(new ol.geom.Circle(evt.coordinate, radius * 1000), 16 * radius);
tryPoints(outerCircle.getCoordinates()[0].slice(0, -1));
}
});
}
});
</script>
</body>
</html>

Related

How to add vertical lines and annotations Google timeline chart

I am using a google timeline similar to the code snippet below. I want my chart to look like the one below. I have managed to get everything to work expect how to add the dashed lines and text notation. Unfortunately, when I am searching for annotations I keep getting the AnnotatedTimeline, which is a different google chart.
Is there a simple way to do this?
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['timeline']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'President' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows([
[ 'Washington', new Date(1789, 3, 30), new Date(1797, 2, 4) ],
[ 'Adams', new Date(1797, 2, 4), new Date(1801, 2, 4) ],
[ 'Jefferson', new Date(1801, 2, 4), new Date(1809, 2, 4) ]]);
chart.draw(dataTable);
}
</script>
</head>
<body>
<div id="timeline" style="height: 180px;"></div>
</body>
</html>
I was able to get this to work by finding the position of the rects. I started by drawing divs for each line I would want to show. Then after the timeline is draw I repositions those divs based on the location of the rectangle. I was not able to get a good minimal working snippet here because of the window positions used in the snippet code, but I got pretty close. In my own code I have it working perfectly.
.hline {
border-left: 5px solid black;
height: 100px;
position:absolute;
visibility:hidden;
top:144px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<body>
<div id="timeline" style="height: 180px;"></div>
<div id = "Hline1" class= "hline" > <div style = "position: relative; top:-18px">HLine1</div>
<div id = "Hline2" class= "hline" > <div style = "position: relative; top:-18px">HLine2</div>
<div id = "Hline3" class= "hline" > <div style = "position: relative; top:-18px">HLine3</div>
</div>
</body>
<script>
var options = {
timeline: { showRowLabels: false }
};
const lime="#00ff00" //color for average time
google.charts.load('current', {'packages':['timeline']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Project Stage', });
dataTable.addColumn({ type: 'string', id: 'Bar'});
dataTable.addColumn({ type: 'string', role: 'style'});
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows([
[ 'Washington','Washington',lime, new Date(1789, 3, 30), new Date(1797, 2, 4) ],
[ 'Adams', 'Adams',lime, new Date(1797, 2, 4), new Date(1801, 2, 4) ],
[ 'Jefferson','Jefferson',lime, new Date(1801, 2, 4), new Date(1809, 2, 4) ]]);
chart.draw(dataTable,options);
function redraw (){
var rects = $('rect') //get all rectangles on plot.
function checkColor(arr){
var results = [];
for (let i of arr){
var colorCheck=$(i).attr('fill')
var x =$(i).attr('x')
var width = $(i).attr('width')
var x2 =parseFloat(x)+parseFloat(width)
if(colorCheck == lime){results.push(x2)}
};
return results
};
var linPositions = checkColor(rects) //get x coordinates for vertical lines
var yStart = $('rect')
//console.log(linPositions)
yStart = $(yStart[0]).offset().top;
xMargin=$("#timeline").offset().left;
var yHeight = $('rect')
yHeight = $(yHeight[0]).attr('height');
var lineNames=['Hline1','Hline2','Hline3']
for (let i = 0; i < linPositions.length; i++) {
var position = linPositions[i]+xMargin+"px"
var newTop = i*yHeight + yStart
/* set line information based on current chart positions */
document.getElementById(lineNames[i]).style.left = position;
document.getElementById(lineNames[i]).style.visibility = "visible";
document.getElementById(lineNames[i]).style.top = newTop;
document.getElementById(lineNames[i]).style.height = yHeight;
};
};
redraw()
function resizeChart () {
chart.draw(dataTable, options);
}
if (document.addEventListener) {
window.addEventListener('resize', resizeChart);
window.addEventListener('resize', redraw)
}
else if (document.attachEvent) {
window.attachEvent('onresize', resizeChart);
window.attachEvent('onresize', redraw);
}
else {
window.resize = resizeChart;
window.resize = redraw;
}
}
</script>
</html>

Stacked column Google chart overlapping label inside the column

I'm using stacked column google chart but annotation or label of each column of graph is overlapping as like the image below:
My code is as below:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<div id="chart_divgraph" style="width: 750px; height:500px;"></div>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script language="javascript">
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawVisualization32);
function drawVisualization32() {
// Some raw data (not necessarily accurate)
/*var jsonData = $.ajax({
url: "getndata.php?cntnew=Ghatwar",
dataType: "json",
async: false
}).responseText;*/
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable({"cols":[{"id":"","label":"Caste Section","pattern":"","type":"string"},{"id":"","label":"Private","pattern":"","type":"number"},{"id":"","label":"Community","pattern":"","type":"number"},{"id":"","label":"Open Defecation","pattern":"","type":"number"}],"rows":[{"c":[{"v":"SC","f":null},{"v":"0","f":null},{"v":"1","f":null},{"v":"47","f":null}]},{"c":[{"v":"ST","f":null},{"v":"3","f":null},{"v":"7","f":null},{"v":"51","f":null}]},{"c":[{"v":"OBC","f":null},{"v":"5","f":null},{"v":"6","f":null},{"v":"84","f":null}]},{"c":[{"v":"GEN","f":null},{"v":"17","f":null},{"v":"1","f":null},{"v":"26","f":null}]}],"p":null});
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
{ calc: getpercentage,
sourceColumn: 1,
type: "string",
role: "annotation" },
2,
{ calc: getpercentagesecond,
sourceColumn: 2,
type: "string",
role: "annotation" },
3,
{ calc: getpercentagethird,
sourceColumn: 3,
type: "string",
role: "annotation" }])
function getpercentage(data, rowNum){
var firstval = data.getValue(rowNum, 1)
var secondval = data.getValue(rowNum, 2)
var thirdval = data.getValue(rowNum, 3)
var datavalueplus = parseInt(firstval) + parseInt(secondval) + parseInt(thirdval);
var finalpercentage = Math.abs( (firstval/datavalueplus)*100 ) ;
var numb = finalpercentage.toFixed(2);
return (numb + "%");
}
function getpercentagesecond(data, rowNum){
var firstval = data.getValue(rowNum, 1)
var secondval = data.getValue(rowNum, 2)
var thirdval = data.getValue(rowNum, 3)
var datavalueplus = parseInt(firstval) + parseInt(secondval) + parseInt(thirdval);
var finalpercentage = Math.abs( (secondval/datavalueplus)*100 ) ;
var numb = finalpercentage.toFixed(2);
return (numb + "%");
}
function getpercentagethird(data, rowNum){
var firstval = data.getValue(rowNum, 1)
var secondval = data.getValue(rowNum, 2)
var thirdval = data.getValue(rowNum, 3)
var datavalueplus = parseInt(firstval) + parseInt(secondval) + parseInt(thirdval);
var finalpercentage = Math.abs( (thirdval/datavalueplus)*100 ) ;
var numb = finalpercentage.toFixed(2);
return (numb + "%");
}
var options = {
title : 'Use of toilets across different prevailing caste section in village',
seriesType: 'bars',
/* width: 600,
height: 400,*/
/* bar: { groupWidth: 20 }, */
vAxis: {
/*minValue: 0,*/
/* scaleType: 'mirrorLog',*/
viewWindowMode:'pretty',
},
isStacked:"percent"
};
var chart = new google.visualization.ComboChart(document.getElementById('chart_divgraph'));
chart.draw(view, options);
}
</script>
</body>
</html>
I tried various solution on stackoverflow but didn't get result. Can any one help my on this please? Thanks in advance

Fusion Tables Layer Query permanent tile loading issues

I've been using Google Fusion Tables periodically for a few years, though I'm still a novice.
I've recently been charged with querying one of my tables on a geo-spatial relationship. I found a great example that functions exactly as I need it to, and updated the code with my tableId, ensured that the location column was exactly the same (spelling, capitalization, etc), but when I try to update the map layer, it gives me a permanent "Data may still be loading. Drag or refresh to find out!" on the tiles. My table is public, the data downloadable... I'm not sure what I'm missing.
I'm stumped. I've included the code below and simply used // to disable the tableid from the example.
Any assistance/suggestions would be greatly appreciated!
~Nicole
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Austin TX Delivery Locations</title>
<style>
body { font-family: Arial, sans-serif; padding: 0px; margin: 0px; }
#map_canvas { height: 80%; width:100%; }
#query{font-family:courier;}
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var tableid = '11QnfV_1v3N5GQs70e13SRxGR6_zYOSFJlCpMuD3C';
//var tableid = 790805;
function initialize() {
map = new google.maps.Map(document.getElementById('map_canvas'), {
center: new google.maps.LatLng(30.35, -97.70),
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
google.maps.event.addListener(map, 'click', function(event) {
latlng = event.latLng;
updateQuery();
});
query = {
select: 'address',
from: tableid
}
layer = new google.maps.FusionTablesLayer(tableid);
layer.setMap(map);
}
function updateQuery(){
var limit = document.getElementById('limit').value;
var lat = parseInt(latlng.lat() * 1000) / 1000;
var lng = parseInt(latlng.lng() * 1000) / 1000;
query = "SELECT address FROM " + tableid;
query += " ORDER BY ST_Distance(address, LatLng(" + lat + ',' + lng + "))";
query += " LIMIT " + limit;
layer.setQuery(query);
document.getElementById('query').innerHTML = layer.getQuery();
}
</script>
</head>
<body onLoad="initialize()">
<div id="map_canvas"></div>
<input type="text" id="limit" value="50" onChange="javascript:updateQuery()"/>
<div id="query"></div>
</body>
</html>
When you see the ""Data may still be loading." message it usually means your query is invalid.
Your example has an old "numeric" table id. The syntax for the new "encrypted" table ids is different (and as currently documented)
Constructor Description
FusionTablesLayer(options:FusionTablesLayerOptions) A layer that displays data from a Fusion Table.
Change:
query = {
select: 'address',
from: tableid
}
layer = new google.maps.FusionTablesLayer(tableid);
layer.setMap(map);
To:
query = {
select: 'address',
from: tableid,
};
layer = new google.maps.FusionTablesLayer({query: query });
layer.setMap(map);
And your query in updateQuery to:
query = {
select: 'address',
from: tableid,
limit: limit,
orderBy: ST_Distance(address, LATLNG(" + lat + ',' + lng + "))"
}
layer.setQuery(query);
working fiddle
code snippet:
var tableid = '11QnfV_1v3N5GQs70e13SRxGR6_zYOSFJlCpMuD3C';
//var tableid = 790805;
var latlng;
function initialize() {
map = new google.maps.Map(document.getElementById('map_canvas'), {
center: new google.maps.LatLng(30.35, -97.70),
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
google.maps.event.addListener(map, 'click', function(event) {
latlng = event.latLng;
updateQuery(latlng);
});
query = {
select: 'address',
from: tableid
};
layer = new google.maps.FusionTablesLayer({
query: query
});
layer.setMap(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
function updateQuery(latlng) {
var limit = document.getElementById('limit').value;
query = {
select: 'address',
from: tableid,
limit: limit,
orderBy: 'ST_Distance(address, LATLNG(' + latlng.lat() + ',' + latlng.lng() + '))'
}
layer.setQuery(query);
var queryObj = layer.getQuery()
var queryStr = "from:" + queryObj.from + "<br>";
queryStr += "select:" + queryObj.select + "<br>";
queryStr += "limit:" + queryObj.limit + "<br>";
queryStr += "orderBy:" + queryObj.orderBy + "<br>";
document.getElementById('query').innerHTML = queryStr;
}
html,
body {
font-family: Arial, sans-serif;
padding: 0px;
margin: 0px;
height: 100%;
width: 100%;
}
#map_canvas {
height: 80%;
width: 100%;
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map_canvas"></div>
<input type="text" id="limit" value="50" onChange="javascript:updateQuery()" />
<div id="query"></div>

Google Chart API - Change value with mouse click (setValue)

I have created a donut chart from Google Charts API. When clicking on each slice, it should increase by 10 units and decrease the adjacent slice (clockwise) by 10 units. What I have thus far is a alert popup that explains this, but I would like to redraw the chart with the new values.
Here is my code:
<html>
<head>
<!--Load the AJAX API-->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
// Load the Visualization API and the piechart package.
google.load('visualization', '1.0', {'packages':['corechart']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
// Create the data table.
var data = new google.visualization.DataTable();
data.addColumn('string', 'Option');
data.addColumn('number', 'Value');
data.addRows([
['Option A', 40],
['Option B', 30],
['Option C', 30]
]);
// Set chart options
var options = {
height: 300,
fontName: 'Lato, sans-serif',
title: 'Values per option',
titleTextStyle: {
color: '#5a5a5a',
fontSize: 20,
bold: true,
align: 'center'
},
pieHole: 0.6,
slices: {
0: {color: 'red'},
1: {color: 'blue'},
2: {color: 'green'}
},
legend: {
position: 'bottom',
textStyle: {
color: '#5a5a5a',
fontSize: 14
}
},
enableInteractivity: true,
pieSliceText: 'none'
};
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
function selectHandler() {
var selectedItem = chart.getSelection()[0];
if (selectedItem && selectedItem.row <2) {
var activeTrait = data.getValue(selectedItem.row, 0);
activePerc = data.getValue(selectedItem.row, 1);
activePercNew = parseInt(activePerc)+10
adjaceTrait = data.getValue(selectedItem.row+1, 0);
adjacePerc = data.getValue(selectedItem.row+1, 1);
adjacePercNew = parseInt(adjacePerc)-10
alert(activeTrait + ' has a value of ' + activePerc + '%. The new value will now be set to ' + activePercNew + '% and ' + adjaceTrait + ' will be corrected to ' + adjacePercNew + '%.');
}
if (selectedItem && selectedItem.row == 2) {
var activeTrait = data.getValue(selectedItem.row, 0);
activePerc = data.getValue(selectedItem.row, 1);
activePercNew = parseInt(activePerc)+10
adjaceTrait = data.getValue(selectedItem.row-2, 0);
adjacePerc = data.getValue(selectedItem.row-2, 1);
adjacePercNew = parseInt(adjacePerc)-10
alert(activeTrait + ' has a value of ' + activePerc + '%. The new value will now be set to ' + activePercNew + '% and ' + adjaceTrait + ' will be corrected to ' + adjacePercNew + '%.');
}
}
google.visualization.events.addListener(chart, 'select', selectHandler);
chart.draw(data, options);
}
</script>
</head>
<body>
<!--Div that will hold the pie chart-->
<div id="chart_div" style="width:800; height:300"></div>
</body>
</html>
I would just like to resize the selected and adjacent slices by clicking on a single slice. Not sure if I should create a var newdata with the changed values and use chart.draw(newdata, option)?
Yeah you're pretty much there, and you're definitely on the right track with your answer. You can use data.setValue() to adjust your values then you would have something like this in your second "if" statement:
data.setValue(selectedItem.row,1, activePercNew);
data.setValue(selectedItem.row-2,1, adjacePercNew);
chart.draw(data, options);
// the thing we just clicked on was redrawn so it lost its handler, reinstate it:
google.visualization.events.addListener(chart, 'select', selectHandler);
And the same in the first but with selectedItem.row+1 instead of selectedItem.row-2. Or, ideally, tidy that section up a little so the two if statements figure out which things you're referring to and then one bit of code does the redraw. For example, here's an adjusted handler function which also doesn't rely on there being 3 sections:
function selectHandler() {
var selectedItem = chart.getSelection()[0];
var numRows = data.getNumberOfRows();
// verify the selection isn't inexplicibly invalid
if (selectedItem && selectedItem.row < numRows && selectedItem.row >= 0) {
// find the two items we're looking at
var curItem = selectedItem.row;
// we either want selected.row + 1 or we want 0 if the selected item was the last one
var otherItem = selectedItem.row == numRows - 1 ? 0 : selectedItem.row + 1;
// calculate the new values
var activePerc = data.getValue(curItem , 1);
var activePercNew = parseInt(activePerc)+10;
var adjacePerc = data.getValue(otherItem , 1);
var adjacePercNew = parseInt(adjacePerc )-10;
// update the chart
data.setValue(curItem,1, activePercNew);
data.setValue(otherItem,1, adjacePercNew);
chart.draw(data, options);
// the thing we just clicked on was redrawn so it lost its handler, reinstate it:
google.visualization.events.addListener(chart, 'select', selectHandler);
}
}
You might want to then also consider what should happen if a value is forced right to zero - with this solution it'll disappear from the chart, and then the next click will force an invalid negative value.

display data in specific areas on google scatter

I have a google scatter graph like this:
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Age', 'Weight'],
[ 8, 12],
[ 4, 5.5],
[ 11, 14],
[ 4, 5],
[ 3, 3.5],
[ 6.5, 7]
]);
var options = {
title: 'Age vs. Weight comparison',
hAxis: {title: 'Age', minValue: 0, maxValue: 15},
vAxis: {title: 'Weight', minValue: 0, maxValue: 15},
legend: 'none'
};
var chart = new google.visualization.ScatterChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="chart_div" style="width: 900px; height: 500px;"></div>
</body>
</html>
I would like when click on a circle, showing only those cycles that are within a radius x from the choosen circle. Any idea??
Thank you!
You need to filter the DataTable to get all of the points within the given radius of the selected point. Here's some code that will do this for you:
google.visualization.events.addListener(chart, 'select', function () {
var selection = chart.getSelection();
if (selection.length > 0) {
// get all data points within radius r of the selected point
var r, x, y;
r = <the radius to use>;
x = data.getValue(selection[0].row, 0);
y = data.getValue(selection[0].row, 1);
var rows = [];
for (var i = 0, count = data.getNumberOfRows(), dx, dy; i < count; i++) {
dx = data.getValue(i, 0) - x;
dy = data.getValue(i, 1) - y;
if (Math.sqrt(dx * dx + dy * dy) <= r) {
rows.push(i);
}
}
// do something with filtered rows
}
});
Here's a proof-of-concept demonstrating how it works: http://jsfiddle.net/asgallant/tgshL/