I'm trying to make a Google Map or MyMap that will display a district in a red shape. I know I need the coordinates of the district from my country (France); I found this link to download GADM data.
But what can I do with this file? How can I get the coordinates from it?
I know the steps after that, with the coordinates, I need to use this utility.
Are you trying to add a Google map to a website? If so, you can use Google Maps API to create a map and add a KML layer as shown here: https://developers.google.com/maps/documentation/javascript/examples/layer-kml
I would not use a polyline utility at all. Download the data you need with the appropriate level (from 0 to 5) from the website you found in KMZ format, unpack it to extract KML and use it as a layer source with Google Maps API.
If your topic has to do with digital maps https://gis.stackexchange.com/ is where you can get answers faster.
See this simple example:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<title>Regions of France</title>
<style>
#map {
height: 100%;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 6,
center: {lat: 47.147583, lng: 2.420839}
});
var ctaLayer = new google.maps.KmlLayer({
url: 'http://evnica.com/kml/France5.kml',
map: map
});
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>
</body>
</html>
Note that you need to have a Google API key. The link to the KML file used in this example is temporary. If you want to use this file, please download it and host it on your server.
Related
I have a React application with server side rendering. I now have to implement Facebook/Google+ share dialog with og:title and og:image being set dynamically to values returned from the API.
I'm using react-helmet to set my default meta tags, however I have troubles making it work dynamically.
I tried using redux-async-connect to prefetch the result, which resulted in meta tags being rendered (I can see them when I look at the source code), however both Facebook and Google+ ignore them.
Do any of you have experience with making this work?
Essentially, in your public/index.html file you want to replace the metadata with an identifiable string:
<!-- in public/index.html -->
<title>$OG_TITLE</title>
<meta name="description" content="$OG_DESCRIPTION" />
<meta property="og:title" content="$OG_TITLE" />
<meta property="og:description" content="$OG_DESCRIPTION" />
<meta property="og:image" content="$OG_IMAGE" />
And then on the server, you want to replace these strings with the dynamically generated information. Here is an example route with Node and Express:
app.get('/about', function(request, response) {
console.log('About page visited!');
const filePath = path.resolve(__dirname, './build', 'index.html')
fs.readFile(filePath, 'utf8', function (err,data) {
if (err) {
return console.log(err);
}
data = data.replace(/\$OG_TITLE/g, 'About Page');
data = data.replace(/\$OG_DESCRIPTION/g, "About page description");
result = data.replace(/\$OG_IMAGE/g, 'https://i.imgur.com/V7irMl8.png');
response.send(result);
});
});
Taken from this tutorial here: https://www.kapwing.com/blog/how-to-add-dynamic-meta-tags-server-side-with-create-react-app/
You can render the app inside document like this:
render(<App/>, document)
while App containing all the html you need.
I'm working on a chrome extension that uses the iframe.ly API to grab the responsive iframe markup from a video on the page the user is currently on. I'm using Angular JS (v1.5.8) to communicate with the API, and to generate a preview of the iframe markup. Everything's working splendidly if the extension is being used on a YouTube page. Here's the basic flow:
content script <-- grabs current url
chrome.runtime.sendMessage({
theurl: window.location.href
});
background script <-- puts current url into url made for the API call:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse){
localStorage["theurl"] = request.theurl;
}
);
var url = "http://iframe.ly/api/iframely?url="
+ localStorage["theurl"] + "&api_key=**my api key, to be removed in production**>";
stuff.js <-- not greatly named, but the Angular bit that makes the call:
var iframeApp = angular.module('iframeApp', ['ngSanitize']);
iframeApp.controller('linkCtrl', function($scope, $http) {
$http.get(url).success(function(data) {
$scope.iframe = data;
});
});
iframeApp.filter('trusted', ['$sce', function ($sce) {
return function(url) {
return $sce.trustAsResourceUrl(url);
};
}]);
iframeApp.filter('rawHtml', ['$sce', function($sce){
return function(val) {
return $sce.trustAsHtml(val);
};
}]);
sandboxed.html <-- again, not greatly named (leftover from when I was trying a different approach for this extension), but the default popup when browser icon is clicked:
<html class="ng-scope" ng-csp ng-app="iframeApp">
<head>
<meta charset="utf-8">
<title>Angular.js JSON Fetching Example</title>
<link rel="stylesheet" href="bootstrap.min.css">
<script src="angular.min.js"></script>
<script src="angular-sanitize.min.js"></script>
<script src="backgroundscript.js"></script>
<script src="stuff.js"></script>
</head>
<body ng-controller="linkCtrl">
<h4>Responsive iFrame code is <pre>{{iframe.links.player[0].html}}</pre></h4>
<div ng-bind-html="iframe.links.player[0].html | rawHtml"></div>
</body>
</body>
</html>
Now! On a YouTube page (for example), this is what happens when the browser icon is clicked:
Wonderful! BUT! Things get a bit, um, not working at all when I attempt to make the same call when on a Vimeo page. Here's the problem: The source url on the iframe.ly API call to a YouTube page returns a URL that's appended with a https protocol. However, a Vimeo call returns a URL with a non-relative, "//" protocol appended to the source. So, this happens, because obviously this won't work unless you're doing it on an HTML file that's running on a server of some sort, because it otherwise attempts to access a local file:
Now, I'd like to fix this by calling for the source url (by replacing the iframe.links.player[0].html with iframe.links.player[0].href) and then putting that inside an iframe inside of a hardcoded responsive div element. That way, my call would return, say //player.vimeo.com/video/177375994?byline=0&badge=0&portrait=0&title=0.
So, how could I remove all the protocols from the URLs from the API calls? This would be great, because player.vimeo.com/video/177375994?byline=0&badge=0&portrait=0&title=0 automatically routes the browser to append the proper protocol, rather than making it think that I'm trying to load a local file, and it does the same when there's no protocol on a YouTube URL, and I'm assuming any other URL for a video as well.
The functionality of the extension is to allow a developer to quickly copy/paste iframe markup, instead of having to type it out, just to make things a tad easier. So, the "//" protocol would actually be fine in the long run if a site is being built, because then it's running on a server, and it doesn't matter. But, for purposes of not looking ugly, it'd be nice if the preview worked for all videos with the extension.
Thank you!
In case you're working on an extension or app with Angular, and you're communicating with public API that you don't have control over, and that API is giving you some guff with some unwanted characters its responses: Never fear!
I successfully pulled the protocol from the get request's returning URL, but after realizing that a URL without a protocol is treated like a local file, too, I added an "http://" protocol to the URL after stripping it. This way, any Vimeo source in the iframe.ly API that had a protocol of "//" would be replaced with an "http://", which ends up redirecting it to an "https://" protocol anyway (it seems safe to put "http://" on anything and have your bases covered, because, at least in Chrome, it'll be sufficient to route to anything SSL protected as well).
So, basically, the problem was that the iframe.ly API was spectacular for finding the source URLs for videos, but the protocols weren't normalized, which caused problems when trying to use those URLs inside of the chrome extension. Here's the code I'm currently using to pull the URLs from the API, and then normalize their protocols to all be "http://":
In the poorly named stuff.js, where the Angular code for the extension lives:
var iframeApp = angular.module('iframeApp', ['ngSanitize']);
iframeApp.controller('linkCtrl', function($scope, $http, $sce) {
$http.get(url).success(function(data) {
$scope.iframe = data;
var newurl = $scope.iframe.links.player[0].href;
var secondurl = newurl.split('/').slice(2).join('/');
$scope.iframe2 = $sce.trustAsResourceUrl((secondurl.indexOf('://') == -1) ? 'http://' + secondurl : secondurl) ;
var testurl = $scope.iframe.links.player[0].href;
$scope.iframe3 = testurl;
$scope.iframe3 = $sce.trustAsResourceUrl(testurl);
});
});
iframeApp.filter('trusted', ['$sce', function ($sce) {
return function(url) {
return $sce.trustAsResourceUrl(url);
};
}]);
iframeApp.filter('rawHtml', ['$sce', function($sce){
return function(val) {
return $sce.trustAsHtml(val);
};
}]);
And, in the also-poorly-named sandboxed.html, which is the extension's default popup:
<html class="ng-scope" ng-csp ng-app="iframeApp">
<head>
<meta charset="utf-8">
<title>Angular.js JSON Fetching Example</title>
<link rel="stylesheet" href="bootstrap.min.css">
<script src="angular.min.js"></script>
<script src="angular-sanitize.min.js"></script>
<script src="backgroundscript.js"></script>
<script src="stuff.js"></script>
</head>
<body ng-controller="linkCtrl">
<h4>Responsive iFrame: <pre><code><div style="left: 0px; width: 100%; height: 0px; position: relative; padding-bottom: 56.2493%;"><iframe src="{{iframe2}}" frameborder="0" allowfullscreen="true" webkitallowfullscreen="true" mozallowfullscreen="true" style="top: 0px; left: 0px; width: 100%; height: 100%; position: absolute;"></iframe></div></code></pre>
<div>Source URL is: <code>{{iframe2}}</code></div>
<div style="left: 0px; width: 100%; height: 0px; position: relative; padding-bottom: 56.2493%;"><iframe ng-src="{{iframe2}}" frameborder="0" allowfullscreen="true" webkitallowfullscreen="true" mozallowfullscreen="true" style="top: 0px; left: 0px; width: 100%; height: 100%; position: absolute;"></iframe></div>
</body>
</html>
And now, clicking the browser action icon on a Vimeo video's page will not return with the Sad Face graphic that I've come to loathe so, so very much over the past couple weeks:
And, if I copy/paste that source URL into the browser, we can see that it automatically routes the "http://" protocol to its rightful "https://" protocol:
And, just for fun, an html page that's populated with stuff copy/pasted from the Responsive iFrame Code section of the default popup:
Gives us this, when the file is opened locally:
I have a feeling that any AngularJS purist is looking at this code and shouting "NO NO NO NO NO" at their screen, because, even as a n00b, I'm pretty sure that this Angular code is ugly, and should be separated into different pieces. BUT! It is working, and I'd love to hear any suggestions on accomplishing this in a more proper, "Angular Way" :)
I am building a Chrome extension using AngularJS that is using Google Maps (specifically Locations).
I am looking for functionality that is similar to
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style type="text/css">
body
{
font-family: Arial;
font-size: 10pt;
}
</style>
</head>
<body>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>
<script type="text/javascript">
google.maps.event.addDomListener(window, 'load', function () {
var places = new google.maps.places.Autocomplete(document.getElementById('txtPlaces'));
google.maps.event.addListener(places, 'place_changed', function () {
var place = places.getPlace();
var address = place.formatted_address;
var latitude = place.geometry.location.lat();
var longitude = place.geometry.location.lng();
var mesg = "Address: " + address;
mesg += "\nLatitude: " + latitude;
mesg += "\nLongitude: " + longitude;
alert(mesg);
});
});
</script>
<span>Location:</span>
<input type="text" id="txtPlaces" style="width: 250px" placeholder="Enter a location" />
</body>
</html>
The above works fine if it's not a Chrome extension. However, because I'm building a Chrome extension when I try to load the Google Maps script
http://maps.googleapis.com/maps/api/js?sensor=false&libraries=places
I get an error saying
Refused to load the script 'http://maps.googleapis.com/maps/api/js?sensor=false&libraries=places' because it violates the following Content Security Policy directive: "script-src 'self' https://ssl.google-analytics.com".
When I change the manifest to
"content_security_policy": "script-src 'self' https://maps.googleapis.com https://ssl.google-analytics.com; object-src 'self'",
I still get the same 'Refused to load script' error.
So my question is: how do I load the Google Maps library without loading it directly in the HTML file?
I was able to add https://maps.googleapis.com to the manifest. It wasn't working before because I wasn't reloading the files to chrome. Now that I reloaded, that is working!
By default, inline script won't be executed and only local script is loaded.
Besides adding remote url (starting with https) in content_securiy_policy field, you should also extract your inline script to an external file then include it.
I'm using Grails 2.4.4 and AngularJS 1.3.15 to create a simple application. To make templates work with Grails I use the AngularJS Template Asset-Pipeline Plugin 2.0.7.
My first prototype was not using any routing logic from ngRoute. Now I want to extract parts of the growing application and put them in separate templates. This almost worked but I have a problem with images. Previously I used constructs like this to load images as assets:
<img src="${assetPath(src: 'image.png')}">
That did work because the whole app was a .gsp page. Extracting the code into templates this processing does not happen anymore and the images cannot be loaded anymore.
My current workaround is:
<img src="../assets/image.png">
Obviously this technique has some drawbacks. Hardcoding the asset location with a relative path can be very fragile. Did I miss some nice feature or command that could help me here merging AngularJS with Asset Pipeline?
I 'got around' this issue by adding an 'AssetService' to my Angularjs project.
angular.module('myApp.assets')
.service('AssetService', [ function () {
this.getAssetDir = function() {
return window.grailsSupport.assetsRoot;
};
this.getRootDir = function() {
return window.grailsSupport.root;
};
}]);
This requires some code in your Grails Layout File....
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title><g:layoutTitle default="MyApp"/></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="${assetPath(src: 'favicon.ico')}" type="image/x-icon">
<link rel="apple-touch-icon" href="${assetPath(src: 'apple-touch-icon.png')}">
<link rel="apple-touch-icon" sizes="114x114" href="${assetPath(src: 'apple-touch-icon-retina.png')}">
<!-- add this to your layout -->
<g:javascript>
window.grailsSupport = {
assetsRoot : '${ raw(asset.assetPath(src: '')) }',
root : '${createLink(uri: '/')}'
};
</g:javascript>
<asset:stylesheet src="application.css"/>
<asset:javascript src="application.js"/>
<g:layoutHead/>
</head>
I got the window.grailsSupport code in an answer to another stack overflow question.
You can now use the AssetService to prefix your URLs in your controllers...
angular.module('MyApp.profile')
.controller('MyCtrl', [ 'AssetService', '$http', function(AssetService, $http) {
var self = this;
self.pathToAnonProfile = AssetService.getAssetDir() + "ppt_Anonymous.jpg";
$http.get(AssetService.getRootDir() + 'api/v1/users').then(function(response) {
....
}, function(errResponse) {
....
});
}]);
It could most likely be improved and you still need to mix gsp and pure Angular templates but it keeps the Asset path in a single service which can easily be modified.
It looks like the tag and the corresponding assetPath() are broken in this respect. They do not appear to respect the serverURL setting in config.groovy or calculate the base path properly when rendering in a template.
I was able to work around the issue in a less fragile way using the createLink() tag to generate my path. It fixes the name of the asset controller, but I think it unlikely that they will change that.
In my case I was resolving some flag images within an AJAX callback.
<img src='${createLink(controller: "assets", action: "flags/16/US.png")}' />
Hopefully this works for you as well.
i try to put my kml file on google maps using geoxml3. here is the code`
<script src="https://maps.googleapis.com/maps/api/js?&sensor=false"></script>
<script type="text/javascript" src="http://geoxml3.googlecode.com/svn/branches/polys/geoxml3.js"></script>
<script>
function initialize() {
var myLatlng = new google.maps.LatLng(-3.899540, 104.463014);
var mapOptions = {
zoom: 4,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
myParser = new geoXML3.parser({map: map});
myParser.parse('bpnsumsel.kml');
}
</script>
`
but nothing shows up.
any idea?
update:
my kml file looks like this
<?xml version="1.0" encoding="utf-8"?><kml xmlns="http://earth.google.com/kml/2.0"><GroundOverlay><name> MapInfo Saved View</name><visibility>1</visibility><Icon><href>Peta BPN Sumsel.JPG</href></Icon><LatLonBox><north>-3.378408</north><south>-4.506592</south><east>105.590007</east><west>103.723993</west><rotation>0</rotation></LatLonBox></GroundOverlay></kml>
yes. i don't include ProjectedOverlayed.js
is there any good tutorial for full code example?
thanks
Per the documentation:
The geoxml3 library is specifically designed to accomodate a range of use cases, covering
developer needs from beginner to advanced. In all cases, you'll need to download a copy of
geoxml3.js (and ProjectedOverlay.js, if you want ground overlays) from this site and serve
them to your map page from your own host, as follows:
<script type="text/javascript" src="geoxml3.js"></script>
[ <script type="text/javascript" src="ProjectedOverlay.js"></script> ]