That code works perfectly for Latitude and Longitude format :
<!DOCTYPE html>
<html>
<body>
<h1>My First Google Map</h1>
<div id="googleMap" style="width:100%;height:400px;"></div>
<script>
function myMap() {
var mapProp= {
center:new google.maps.LatLng(51.508742,-0.120850),
zoom:5,
};
var map=new google.maps.Map(document.getElementById("googleMap"),mapProp);
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBu-916DdpKAjTmJNIgngS6HL_kDIKU0aU&callback=myMap"></script>
<!--
To use this code on your website, get a free API key from Google.
Read more at: https://www.w3schools.com/graphics/google_maps_basic.asp
-->
</body>
</html>
I was wondering if there is any potability to get the location via IP DIRECTLY thru google-maps (without converting the IP to Latitude and Longitude)
Related
I've written a bot and am testing it locally on my machine through the bot emulator. However, my copywriting team want to be able to test it too but don't have the technical skills to set up the emulator.
Is there an easy way I can do this through maybe a Heroku review app (as that is how we currently distribute our app for testing)?
You could create a test page for them with the Web Chat control.
Here's the HTML for one of my chatbots:
<!DOCTYPE html>
<html>
<head>
<title>Pig Latin Bot</title>
<meta charset="utf-8" />
</head>
<body style="font-family:'Segoe UI'">
<img src="images/PigLatinBot.png" alt="Pig Latin Bot"/>
<h1>Pig Latin Bot</h1>
<p>Translates your text to Pig Latin.</p>
<div id="webChatControl">
</div>
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<script type="text/javascript">
$("#webChatControl").load("api/WebChat");
</script>
</body>
</html>
And here's the controller code:
public class WebChatController : ApiController
{
public async Task<string> Get()
{
string webChatSecret = ConfigurationManager.AppSettings["WebChatSecret"];
var request = new HttpRequestMessage(HttpMethod.Get, "https://webchat.botframework.com/api/tokens");
request.Headers.Add("Authorization", "BOTCONNECTOR " + webChatSecret);
HttpResponseMessage response = await new HttpClient().SendAsync(request);
string token = await response.Content.ReadAsStringAsync();
token = token.Replace(""", "");
return $"<iframe width='400px' height='400px' src='https://webchat.botframework.com/embed/PigLatinBotJoeMayo?t={token}'></iframe>";
}
}
There's a more detailed explanation in my blog post, Using the Bot Framework Chat Control.
I don't know how to solve the following: I'd like to let my Model generate real javascript dynamically based on some model logic.
This final piece of javascript code then should be added inside the $(document).ready { } part of my html page.
The thing is: If I use inline="javascript", the code gets quoted as my getter is a String (that is how it is mentioned in the Thymeleaf doc but it's not what I need ;-)
If I use inline="text" in is not quoted but all quotes are escaped instead ;-) - also nice but unusable 8)
If I try inline="none" nothing happens.
Here are the examples
My model getter created the following Javascript code.
PageHelper class
public String documentReady() {
// do some database operations to get the numbers 8,5,3,2
return "PhotoGallery.load(8,5,3,2).loadTheme(name='basic')";
}
So if I now try inline="javascript"
<script th:inline="javascript">
/*<![CDATA[*/
jQuery().ready(function(){
/*[[${pageHelper.documentReady}]]*/
});
/*]]>*/
</script>
it will be rendered to
<script>
/*<![CDATA[*/
jQuery().ready(function(){
'PhotoGallery.load(8,5,3,2).loadTheme(name=\'basic\')'
});
/*]]>*/
</script>
Which doesn't help as it is a String literal, nothing more (this is how Thymeleaf deals with it).
So if I try inline="text" instead
<script>
/*<![CDATA[*/
jQuery().ready(function(){
PhotoGallery.load(8,5,3,2).loadTheme(name='basic')
});
/*]]>*/
</script>
Which escapes the quotes.
inline="none" I do not really understand, as it does nothing
<script>
/*<![CDATA[*/
jQuery().ready(function(){
[[${pageHelper.documentReady}]]
});
/*]]>*/
</script>
To be honest I have no idea how to solve this issue and hopefully anybody out there knows how to deal with this.
Many thanks in advance
Cheers
John
I would change the approach.
Thymeleaf easily allows you to add model variables in your templates to be used in Javascript. In my implementations, I usually put those variables somewhere before the closing header tag; to ensure they're on the page once the JS loads.
I let the template decide what exactly to load, of course. If you're displaying a gallery, then render it as you would and use data attributes to define the gallery that relates to some JS code. Then write yourself a nice jQuery plugin to handle your gallery.
A relatively basic example:
Default Layout Decorator: layout/default.html
<!doctype html>
<html xmlns:layout="http://www.thymeleaf.org" xmlns:th="http://www.thymeleaf.org">
<head>
<title>My Example App</title>
<object th:remove="tag" th:include="fragments/scripts :: header" />
</head>
<body>
<div layout:fragment="content"></div>
<div th:remove="tag" th:replace="fragments/scripts :: footer"></div>
<div th:remove="tag" layout:fragment="footer-scripts"></div>
</body>
</html>
The thing to notice here is the inclusion of the generic footer scripts and then a layout:fragment div defined. This layout div is what we're going to use to include our jQuery plugin needed for the gallery.
File with general scripts: fragments/scripts.html
<div th:fragment="header" xmlns:th="http://www.thymeleaf.org">
<script type="text/javascript" th:inline="javascript">
/*<![CDATA[*/
var MY_APP = {
contextPath: /*[[#{/}]]*/,
defaultTheme: /*[[${theme == null} ? null : ${theme}]]*/,
gallery: {
theme: /*[[${gallery == null} ? null : ${gallery.theme}]]*/,
images: /*[[${gallery == null} ? null : ${gallery.images}]]*/,
names: /*[[${gallery == null} ? null : ${gallery.names}]]*/
}
};
/*]]>*/
</script>
</div>
<div th:fragment="footer" xmlns:th="http://www.thymeleaf.org">
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/my_app.js"></script>
</div>
In the scripts file, there are 2 fragments, which are included from the decorator. In the header fragment, a helpful context path is included for the JS layer, as well as a defaultTheme just for the hell of it. A gallery object is then defined and assigned from our model. The footer fragment loads the jQuery library and a main site JS file, again for purposes of this example.
A page with a lazy-loaded gallery: products.html
<html layout:decorator="layout/default" xmlns:layout="http://www.thymeleaf.org/" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Products Landing Page</title>
</head>
<body>
<div layout:fragment="content">
<h1>Products</h1>
<div data-gallery="lazyload"></div>
</div>
<div th:remove="tag" layout:fragment="footer-scripts">
<script type="text/javascript" src="/js/my_gallery.js"></script>
</div>
</body>
</html>
Our products page doesn't have much on it. Using the default decorator, this page overrides the page title in the head. Our content fragment includes a title in an h1 tag and an empty div with a data-gallery attribute. This attribute is what we'll use in our jQuery plugin to initialize the gallery.
The value is set to lazyload, so our plugin knows that we need to find the image IDs in some variable set somewhere. This could have easily been empty if the only thing our plugin supports is a lazyloaded gallery.
So the layout loads some default scripts and with cleverly placed layout:fragments, you allow certain sections of the site to load libraries independent of the rest.
Here's a basic Spring controller example, to work with our app: MyController.java
#Controller
public class MyController {
#RequestMapping("/products")
public String products(Model model) {
class Gallery {
public String theme;
public int[] images;
public String[] names;
public Gallery() {
this.theme = "basic";
this.images = new int[] {8,5,3,2};
this.names = new String[] {"Hey", "\"there's\"", "foo", "bar"};
}
}
model.addAttribute("gallery", new Gallery());
return "products";
}
}
The Gallery class was tossed inline in the products method, to simplify our example here. This could easily be a service or repository of some type that returns an array of identifiers, or whatever you need.
The jQuery plugin that we created, could look something like so: my_gallery.js
(function($) {
var MyGallery = function(element) {
this.$el = $(element);
this.type = this.$el.data('gallery');
if (this.type == 'lazyload') {
this.initLazyLoadedGallery();
}
};
MyGallery.prototype.initLazyLoadedGallery = function() {
// do some gallery loading magic here
// check the variables we loaded in our header
if (MY_APP.gallery.images.length) {
// we have images... sweet! let's fetch them and then do something cool.
PhotoGallery.load(MY_APP.gallery.images).loadTheme({
name: MY_APP.gallery.theme
});
// or if load() requires separate params
var imgs = MY_APP.gallery.images;
PhotoGallery.load(imgs[0],imgs[1],imgs[2],imgs[3]).loadTheme({
name: MY_APP.gallery.theme
});
}
};
// the plugin definition
$.fn.myGallery = function() {
return this.each(function() {
if (!$.data(this, 'myGallery')) {
$.data(this, 'myGallery', new MyGallery(this));
}
});
};
// initialize our gallery on all elements that have that data-gallery attribute
$('[data-gallery]').myGallery();
}(jQuery));
The final rendering of the products page would look like so:
<!doctype html>
<html>
<head>
<title>Products Landing Page</title>
<script type="text/javascript">
/*<![CDATA[*/
var MY_APP = {
contextPath: '/',
defaultTheme: null,
gallery: {
theme: 'basic',
images: [8,5,3,2],
names: ['Hey','\"there\'s\"','foo','bar']
}
};
/*]]>*/
</script>
</head>
<body>
<div>
<h1>Products</h1>
<div data-gallery="lazyload"></div>
</div>
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/my_app.js"></script>
<script type="text/javascript" src="/js/my_gallery.js"></script>
</body>
</html>
As you can see, Thymeleaf does a pretty good job of translating your model to valid JS and actually adds the quotes where needed and escapes them as well. Once the page finishes rendering, with the jQuery plugin at the end of the file, everything needed to initialize the gallery should be loaded and ready to go.
This is not a perfect example, but I think it's a pretty straight-forward design pattern for a web app.
instead of ${pageHelper.documentReady} use ${pageHelper.documentReady}
I'm having problems with iron-ajax and data binding in Polymer 1.0.2. Not even a slightly changed example from the Polymer documentation is working.
Here is the code with my changes:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../bower_components/iron-ajax/iron-ajax.html">
</head>
<body>
<template is="dom-bind">
<iron-ajax
auto
url="http://jsonplaceholder.typicode.com/posts/"
lastResponse="{{data}}"
handleAs="json">
</iron-ajax>
<template is="dom-repeat" items="{{data}}">
<div><span>{{item.id}}</span></div>
</template>
</template>
<script>
(function (document) {
'use strict';
var app = document.querySelector('#app');
window.addEventListener('WebComponentsReady', function() {
var ironAjax = document.querySelector('iron-ajax');
ironAjax.addEventListener('response', function() {
console.log(ironAjax.lastResponse[0].id);
});
ironAjax.generateRequest();
});
})(document);
</script>
</body>
</html>
All I changed was entering a URL to get a real JSON response and setting the auto and handleAs properties. I also added a small script with a listener for the response event. The listener is working fine and handles the response, but the spans in the dom-repeat template aren't rendered.
I'm using Polymer 1.0.2 and iron-elements 1.0.0
It seems the documentation you is missing a - character in the lastresponse attribute of the example.
You must change lastResponse to last-response.
Look at this example from the iron-ajax github page.
when you use a attribute on a element, you have to convert the camelcase sentence to dashes sentence, I mean:
lastResponse is maps to last-response
Property name to attribute name mapping
I am currently trying to use the Bing Maps AJAX API v7 in the new 'Multi-device hybrid App" template provided in Visual Studio, which uses Apache Cordova to provide crossplatform compatibility. I have written the following code, following the template at http://msdn.microsoft.com/en-us/library/gg427624.aspx :
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head>
<meta charset="utf-8" />
<title>Wand</title>
<!-- Wand references -->
<link href="css/index.css" rel="stylesheet" />
<script charset="UTF-8" type="text/javascript" src="https://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&s=1">
</script>
<script type="text/javascript">
function GetMap() {
var map = new Microsoft.Maps.Map(document.getElementById("map"), { credentials: "AgegeewHkb9iTTQDLseMTuQyxQyZybs7uUv7aqIgKu6U8CiaflVNApy5WtDXqtHr " });
}
</script>
</head>
<body onload="GetMap();">
<div id='map' class="mainview"></div>
<div class="menu">This is the menu</div>
<!-- Cordova reference, this is added to your app when it's built. -->
<script src="cordova.js"></script>
<script src="scripts/index.js"></script>
</body>
</html>
But when I debug it in Windows 8.1, it says that Microsoft is not defined (in the GetMap function). I asume that the library from
https:// ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&s=1
has not been loaded properly. Is there anything wrong with my code? Should I use the AJAX WEB API, or is there another for apps (the only one I have seen is for Windows 8 only)?
I think that my app is unable to load the web library because it doesn't have the proper permisions. In the config.xml there is a domain access section, but it says it doesn't appy to the windows platform, so how can I set it to allow loading pages from https:// ecn.dev.virtualearth.net ?
EDIT: Loading the script from a Web context (ms-appx-web) makes the script run, but if I want the code to be multiplatform I cannot use it. The solution would be to include in the Windows 8 manifest a permission for the Bing maps URL, how can I do it?
INDEX.HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta charset="utf-8" />
<title>Cordova Bing Mapping</title>
<link href="css/index.css" rel="stylesheet" />
<!--Needed for iOS & Android-->
<script charset="UTF-8" type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
</head>
<body>
<div id='map' class="mainview"></div>
<div class="menu">This is the menu</div>
<!-- Cordova reference, this is added to your app when it's built. -->
<script src="cordova.js"></script>
<script src="scripts/index.js"></script>
</body>
INDEX.JS
(function () {
"use strict";
document.addEventListener( 'deviceready', onDeviceReady.bind( this ), false );
//Loads Scripts Dynamically
function loadScript(filename) {
var fileref = document.createElement('script')
fileref.setAttribute("type", "text/javascript")
fileref.setAttribute("src", filename)
}
function onDeviceReady() {
// Load Local Scripts if Windows
if (device.platform == "windows") {
MSApp.execUnsafeLocalFunction(
function () {
loadScript("scripts/veapicore.js"); //Bing Maps SDK VS 2013
loadScript("scripts/veapiModules.js"); //Bing Maps SDK VS 2013
loadScript("scripts/mapcontrol.js"); //downloaded from http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0
Microsoft.Maps.loadModule("Microsoft.Maps.Map", {
callback: loadMap
});
})
}
};
function loadMap() {
var map = new Microsoft.Maps.Map(document.getElementById("map"), {
credentials: "BING_MAPS_KEY"
});
}
})();
NOTES
* This will work on Windows 8, Windows Phone 8, iOS, Android
* Bing Maps SDK VS 2013
1. Download Location: https://visualstudiogallery.msdn.microsoft.com/224eb93a-ebc4-46ba-9be7-90ee777ad9e1
2. Local Location: C:\Users\[USER]\AppData\Local\Microsoft SDKs\Windows\v8.1\ExtensionSDKs\Bing.Maps.JavaScript\1.313.0825.1\redist\commonconfiguration\neutral\Bing.Maps.JavaScript\
* For Windows Phone (Universal) - Microsoft.Maps.loadModule("Microsoft.Maps.Map", { callback: loadMap }); is still undefined.
I've implemented Bing Maps in a "Multi-Device Hybrid App" by doing the following:
Copied the C:\Users\\AppData\Local\Microsoft SDKs\Windows\v8.1\ExtensionSDKs\Bing.Maps.JavaScript\1.313.0825.1\redist\commonconfiguration\neutral\Bing.Maps.JavaScript folder into my local project
Copied http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0 into my local project as remoteBingMaps.js
On "deviceready" (where addScript dynamically adds a script file to document.body)
a. If device.platform == "windows8", then MSApp.execUnsafeLocalFunction(function () {
addScript("Bing.Maps.JavaScript/js/veapicore.js");
addScript("Bing.Maps.JavaScript/js/veapiModules.js");
});
b. Else addScript("scripts/frameworks/remoteBingMaps.js")
When loading the map control (where loadMap initializes the map control)
a. If device.platform == "windows8", then Microsoft.Maps.loadModule("Microsoft.Maps.Map", {callback:loadMap}}
b. Else loadMap()
I've gotten this working for Windows 8.1, Windows Phone, Android, and iOS.
There seems to be a couple of problems with the code.
Firstly, you are directly referencing a library from a URL. That might be causing issues on the Windows platform. You might want to download the file and add it to your project locally.
Secondly, your Bing Maps key has a space at the end, which is why the app is throwing errors at runtime.
<script type="text/javascript">
function GetMap() {
var map = new Microsoft.Maps.Map(document.getElementById("map"), { credentials: "AgegeewHkb9iTTQDLseMTuQyxQyZybs7uUv7aqIgKu6U8CiaflVNApy5WtDXqtHr " });
}
</script>
Change that to:
<script type="text/javascript">
function GetMap() {
var map = new Microsoft.Maps.Map(document.getElementById("map"), { credentials: "AgegeewHkb9iTTQDLseMTuQyxQyZybs7uUv7aqIgKu6U8CiaflVNApy5WtDXqtHr" });
}
</script>
I had the same issue, but neither of the proposed solutions worked for me. Interesting that Bing maps were loaded without any problems on the Ripple Simulator, but on Android emulator or device I had a problem with Microsoft namespace not defined - clearly namespace was not loaded. After some searching I found, that in the config.xml there is configuration for the Whitelist plugin, which controls which pages can be requested from the app (and you can configure that separately for each platform), so I just added:
<allow-intent href="https://ecn.dev.virtualearth.net/mapcontrol/*" />
for the android platform, commented out Content-Security-Policy from index.html and it started to work.
I'm just starting to use Parse Core (as Google'e ScriptDB is being decommissioned soon) and am having some trouble.
So I'm able to get Parse Core db to read/write using just a standard HTML page as shown below:
<!doctype html>
<head>
<meta charset="utf-8">
<title>My Parse App</title>
<meta name="description" content="My Parse App">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/styles.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="http://www.parsecdn.com/js/parse-1.2.18.min.js"></script>
</head>
<body>
<div id="main">
<h1>You're ready to use Parse!</h1>
<p>Read the documentation and start building your JavaScript app:</p>
<ul>
<li>Parse JavaScript Guide</li>
<li>Parse JavaScript API Documentation</li>
</ul>
<div style="display:none" class="error">
Looks like there was a problem saving the test object. Make sure you've set your application ID and javascript key correctly in the call to <code>Parse.initialize</code> in this file.
</div>
<div style="display:none" class="success">
<p>We've also just created your first object using the following code:</p>
<code>
var TestObject = Parse.Object.extend("TestObject");<br/>
var testObject = new TestObject();<br/>
testObject.save({foo: "bar"});
</code>
</div>
</div>
<script type="text/javascript">
Parse.initialize("PyMFUxyBxR8IDgndjZ378CeEXH2c6WLK1wK2JHYX", "IgiMfiuy3LFjzH0ehmyf5Rkti8AmVtwcGqc6nttN");
var TestObject = Parse.Object.extend("TestObject");
var testObject = new TestObject();
testObject.save({foo: "bar"}, {
success: function(object) {
$(".success").show();
},
error: function(model, error) {
$(".error").show();
}
});
</script>
</body>
</html>
However, when I try to serve that up using the HtmlService shown below, I get no response from Parse. Parse Core.html basically has all of the code I have above ( only thing I changed was to remove the css calls).
function doGet() {
var htmlPage = HtmlService.createTemplateFromFile('Parse Core.html')
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.NATIVE)
.setTitle('Parse Core Test');
return htmlPage;
}
Link to ParseDb Library for Apps Script
Here is the key to add the library: MxhsVzdWH6ZQMWWeAA9tObPxhMjh3Sh48
Install that library and it allows you to use most of the same methods that were used by ScriptDb. As far as saving and querying go they almost identical. Make sure to read the Library's notes, how to add the applicationId and restApiKey. It is a little different that you can silo data by classes which must be defined in the call to Parse.
Bruce here is leading the way on database connection for Apps Script, he has plenty of documentation on using Parse.com, and also his own DbConncection Drive that would allow you to use a number of back-end systems.
Excel Liberation - Bruce's Site.