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>
Related
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>
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>
With the code I have it in a script editor on a sharepoint page. I would like to display a message that states "No results found". I have tried over and over and have failed to display.
<!-- Style -->
<style type="text/css">
.item-name-clickable{
font-size:1.1em;
background-color: #c7e0f4;
padding:2px 5px;
margin-top:2px;
cursor:pointer;
}
.item-narrative{
display: none;
border-right:3px #c7e0f4 solid;
border-bottom:3px #c7e0f4 solid;
border-left:3px #c7e0f4 solid;
padding:3px;
}
</style>
<!-- HTML placeholder -->
<div id="COTPTEST_placeholder"></div>
<!-- Script -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript">
function getCOTPItems(){
var date = new Date(), dateISO = "";
date.setDate(date.getDate()-1);
dateISO = String(date.getFullYear()) + "-" + String(date.getMonth()+1) + "-" + String
(date.getDate()) + "T00:00:00Z";
var endpoint = "https://intelshare.intelink.gov/sites/sccnola/COTP/_api/web/lists/getbytitle
('COTP')/items?$filter=(Created ge datetime'"+dateISO+"')&$orderby= Created desc";
jQuery.ajax({
url: endpoint,
method: "GET",
headers: {
"accept": "application/json; odata=verbose",
"content-type": "application/jsom;odata=verbose",
"X-RequestDigest": document.getElementById("__REQUESTDIGEST").value
}
}).done(function (data) {
var b = [];
jQuery.each(data.d.results,function(i,item){
b.push("<div class='item-name-clickable' onclick='jQuery(this).next().slideToggle
(100);'>"+item.name+"</div>");
b.push("<div class='item-narrative'>"+item.Narrative+"</div>");
});
jQuery("#COTP_placeholder").html(b.join(""));
}).fail(function (err) {
jQuery("#COTP_placeholder").html(JSON.stringify(err));
});
}
// Call function
getCOTPtems();
</script>
</code>
I'm trying to load data from a csv-File to create a pie chart.
I found a example and copied it to test it. But it doesn't work. It seems that I'm the only one with this Problem. Whats my fault? Can someone help me?
My html-file:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.arc path {
stroke: #fff;
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script>
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.population; });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
d3.csv("data.csv", function(error, data) {
data.forEach(function(d) {
d.population = +d.population;
});
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.age); });
g.append("text")
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.style("text-anchor", "middle")
.text(function(d) { return d.data.age; });
});
</script>
and the csv:
age,population
<5,2704659
5-13,4499890
14-17,2159981
18-24,3853788
25-44,14106543
45-64,8819342
≥65,612463
Perhaps I have to edit, that I'm using it with django. Without django it works.
So here is my view:
def test(request):
t = get_template('test.html')
html = t.render()
return HttpResponse(html)
how to create a custom combo like above?
here i just did a small hack to the component.by this way you can add any html element to the selection item in combo.
Ext.define('AMShiva.ux.custom.Combo', {
extend: 'Ext.form.field.ComboBox',
alias: 'widget.ux_combo',
colorField: 'color',//to get color value
displayField: 'text',
valueField:'value',
initComponent: function () {
var me = this;
// dropdown item template
me.tpl = Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<div class="x-boundlist-item">',
'<span style="background-color: {' + me.colorField + '};" class="color-box-icon"></span>{' + me.displayField + '}',
'</div>',
'</tpl>'
);
me.callParent(arguments);
// here change the selection item html
me.on('change',
function(element, newValue) {
var inputEl = element.inputCell.child('input');
var data = element.getStore().findRecord(element.valueField, newValue);
if (data) {
inputEl.applyStyles('padding-left:26px');
var parent = inputEl.parent(),
spanDomEle = parent.child('span');
if (!spanDomEle) {
Ext.DomHelper.insertFirst(parent, { tag: 'span', cls: 'color-box-icon' });
var newSpanDomEle = parent.child('span');
newSpanDomEle.applyStyles('background-color: ' + data.get(element.colorField) + ';float: left;position: absolute;margin: 3px 2px 2px 4px;');
} else {
spanDomEle.applyStyles('background-color:' + data.get(element.colorField));
}
}
});
}
});
sample store:
var store = Ext.create('Ext.data.Store', {
fields: ['value', 'text', 'color']
});
css:
.color-box-icon {
width: 16px;
height: 16px;
margin: 0px 4px 0px -3px;
padding: 0px 8px;
}
Is there another way to do this kind of thing?