{"id":6673,"date":"2016-04-11T08:23:24","date_gmt":"2016-04-11T15:23:24","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/webdev\/?p=6673"},"modified":"2016-04-11T08:23:24","modified_gmt":"2016-04-11T15:23:24","slug":"whereyouat-demobuild-2016-building-the-front-end","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/whereyouat-demobuild-2016-building-the-front-end\/","title":{"rendered":"WhereYouAt DemoBuild 2016: Building the Front-end"},"content":{"rendered":"<p>In my <a title=\"WhereYouAt  DemoBuild 2016:  Demo UI\" href=\"http:\/\/marianaggaga.com\/ux-demo-flow\/\">previous post<\/a>, I went over the user interface and application requirements. Let\u2019s quickly revisit the project requirements:<\/p>\n<ul>\n<li>Get coordinates of the users and identify which cloud the ASP.NET Core app is running on.<\/li>\n<li>Populate maps with custom pushpins.<\/li>\n<li>Display the number of containers running on each cloud.<\/li>\n<\/ul>\n<p><!--more--><\/p>\n<p><a href=\"http:\/\/marianaggaga.com\/wp-content\/uploads\/2016\/04\/UItoweb.gif\"><img decoding=\"async\" class=\"alignnone size-full wp-image-16321\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2016\/04\/UItoweb.gif\" alt=\"UItoweb\" width=\"873\" height=\"336\" \/><\/a><\/p>\n<h2>Get Coordinates<\/h2>\n<p>In this app, I am getting the user location with a button using an <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/GlobalEventHandlers\/onclick\">onclick event handler<\/a>. In order to grab the user&#8217;s coordinates, I used the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Geolocation\/Using_geolocation\">Geolocation API<\/a> . Let\u2019s have a look at the code.<\/p>\n<p><!--more--><\/p>\n<p><strong>Get location<\/strong><\/p>\n<pre class=\"brush:js\">function getLocation() {\n    var x = document.getElementById(\"demo\");\n    if (navigator.geolocation) {\n        navigator.geolocation.watchPosition(showPosition);\n    }\n    else {\n        x.innerHTML = \"Geolocation is not supported by this browser.\";\n    }\n}<\/pre>\n<p>getlocation() function simply shows the user longitude and latitude every time you load the page. But, in this case, I needed the user&#8217;s coordinates to put the pins on the map. To do this we created a simple a location <a href=\"http:\/\/www.asp.net\/web-api\">web api<\/a> that, we can PUT our users longitudes and latitude into.<\/p>\n<p><strong>Store location <\/strong><\/p>\n<pre class=\"brush:js\">function showPosition(position) {\n    var lat = position.coords.latitude;\n    var lon = position.coords.longitude;\n    var xhr = new XMLHttpRequest();\n    var params = \"latitude=\" + lat + \"&amp;longitude=\" + lon;\n    console.log(\"Params: \" + params);\n    xhr.open('PUT', '\/locations', true);\n    xhr.setRequestHeader('Content-type', 'application\/x-www-form-urlencoded');\n    xhr.onreadystatechange = function () {\n        console.log(\"Response:\" &amp; this.responseText);\n    };\n    xhr.send(params); \n}\n\n<\/pre>\n<p>You might have noticed I am using XMLHttpRequest API. XMLHttpRequest API is used to transfer data between the client and Server. In this case, we are using it to PUT the users coordinates into a location API.<\/p>\n<p>Since this was a public demo our team thought it might be a good idea to offset the actual coordinate we were receiving. For most people getting their actual coordinates might feel a little creepy to people . To offset the coordinates we added the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Number\/toFixed\">toFixed( ) method<\/a> ; allowing the app to have an idea of where the user is but, not the exact location.<\/p>\n<p><strong><a href=\"https:\/\/github.com\/shanselman\/aspneteverywheredemo\/blob\/master\/src\/whereyouat\/wwwroot\/js\/getloc.js\">Full Script to get geolocation and PUT it into an API<\/a><\/strong><\/p>\n<pre class=\"brush:js\">function getLocation() {\n    var x = document.getElementById(\"demo\");\n    if (navigator.geolocation) {\n        navigator.geolocation.watchPosition(showPosition);\n    }\n    else {\n        x.innerHTML = \"Geolocation is not supported by this browser.\";\n    }\n}\n\nfunction showPosition(position) {\n    var lat = position.coords.latitude.toFixed(2);\n    var lon = position.coords.longitude.toFixed(2);\n    document.getElementById(\"demo\").innerHTML = \"You're around Latitude: \" + lat + \" and Longitude: \" + lon;\n\n    var xhr = new XMLHttpRequest();\n    var params = \"latitude=\" + lat + \"&amp;longitude=\" + lon;\n    console.log(\"Params: \" + params);\n    xhr.open('PUT', '\/locations', true);\n    xhr.setRequestHeader('Content-type', 'application\/x-www-form-urlencoded');\n    xhr.onreadystatechange = function () {\n        console.log(\"Response:\" &amp; this.responseText);\n    };\n    xhr.send(params); \n}\n<\/pre>\n<p>If you would like to explore the geolocation API , check out theses resources: <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Navigator\/geolocation\">Navigator.geolocation<\/a> , <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Geolocation\/getCurrentPosition\">getCurrentPosition<\/a>, and <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Geolocation\/watchPosition\">WatchPosition<\/a>.<\/p>\n<p><strong>Get Location Button<\/strong><\/p>\n<pre class=\"brush:xml\">&lt;a href=\"#\" onclick=\"getLocation();  return false;\" class=\"btn btn-default btn-xl wow tada\"&gt;Get my Location&lt;\/a&gt;<\/pre>\n<h3><strong>Displaying Active Cloud Logo\n<\/strong><\/h3>\n<p><strong>Include @model directive <\/strong><\/p>\n<pre class=\"brush:csharp\">@model whereyouat.Settings<\/pre>\n<p><strong>Display Cloud Name &amp; Logo<\/strong><\/p>\n<pre class=\"brush:xml\">  &lt;h3 id=\"demo\"&gt;&lt;\/h3&gt;\n      @{\n          var largeIcon = $\"~\/img\/large\/{Model.Cloud_Name}.png\";\n       }\n   &lt;h3&gt;You're running ASP.NET on @Model.Cloud_Name!&lt;\/h3&gt;\n   &lt;img src=\"@largeIcon\" alt=\"@Model.Cloud_Name\" \/&gt;\n<\/pre>\n<p>&nbsp;<\/p>\n<p>By including the @model statement at the top of my landing page (<a href=\"https:\/\/github.com\/shanselman\/aspneteverywheredemo\/blob\/master\/src\/whereyouat\/Views\/Home\/Index.cshtml\">Views\/Home\/Index.cshtml<\/a>), I am able to specify the type object that the view expects. By using @model directive gives the view access to Cloud_Name through the <a href=\"https:\/\/github.com\/shanselman\/aspneteverywheredemo\/blob\/master\/src\/whereyouat\/Settings.cs\">settings controller<\/a> .<\/p>\n<p><strong>Results <\/strong><\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/marianaggaga.com\/wp-content\/uploads\/2016\/04\/Cloudgif-2.gif\"><img decoding=\"async\" class=\"alignnone  wp-image-16291\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2016\/04\/Cloudgif-2.gif\" alt=\"Cloudgif (2)\" width=\"763\" height=\"601\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h3>Pushpins<\/h3>\n<p>Start by initializing the map.<\/p>\n<pre class=\"brush:js\">var map;\nfunction getLocations() {\n       var mapOptions = {\n           credentials: \"Bing Key\",\n           mapTypeId: Microsoft.Maps.MapTypeId.road,\n           zoom: 3\n        };\n        map = new Microsoft.Maps.Map(document.getElementById(\"mapDiv\"), mapOptions);\n\n<\/pre>\n<p>I used the JQuery $.get method to retrieve the user&#8217;s coordinates from the location API.<\/p>\n<pre class=\"brush:js\"> $.ajax({\n                type: \"GET\",\n                url: \"\/locations\",\n                dataType: \"json\",\n                success: function (json) {\n                    \/\/console.log(json);\n                    $.each(json, function (i, entry) {\n                        plotEntry(entry.latitude, entry.longitude, entry.cloud_name);\n                    });\n                },\n                error: function (err, status, errortext) {\n                    console.log(errortext);\n                }\n            });\n\n<\/pre>\n<p>For this demo, we wanted to add custom pushpin the showed not only the users locations but, the logos of the cloud their ASP.NET Core was running one. To do this we used the pushpin class. You can also use the pushpin class to add a default pins.<\/p>\n<pre class=\"brush:js\">function plotEntry(latitude, longitude, cloud) {\n            \/\/console.log(latitude + ' ' + longitude);\n\n            \/\/Icons for each Cloud Type\n            var pushpinOptions = { icon: '\/img\/' + cloud + '.png', width: 32, height: 32 };\n            var pushpin = new Microsoft.Maps.Pushpin(\n                new Microsoft.Maps.Location(latitude, longitude),\n                pushpinOptions);\n\n            map.entities.push(pushpin);\n        }\n        $().ready(getLocations);<\/pre>\n<p><strong>Result<\/strong><\/p>\n<p><a href=\"http:\/\/marianaggaga.com\/wp-content\/uploads\/2016\/04\/Maps.png\"><img decoding=\"async\" style=\"padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px\" title=\"Maps\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2016\/04\/Maps_thumb.png\" alt=\"Maps\" width=\"1366\" height=\"643\" border=\"0\" \/><\/a><\/p>\n<h2>Number of request per container<\/h2>\n<p>For the demo, we had a \/cloudcounts api that returns the cloud name, container, and count. The API looked something like this:<\/p>\n<pre class=\"brush:groovy\">{ \"cloud_name\": \"Azure ACS\", \"container\": \"185f65604f23\"\", \"Count\": 14 }<\/pre>\n<p>To obtain the number of request per container , we used a JQuery $.get method similar to what we did to retrieve the user coordinates. The only difference here is, we need to account for the whitespaces in the cloud_name values using the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/encodeURI\">encodeURI<\/a> function. Looking back to our demo requirements, we wanted to so split the number of request per container by cloud name. It would look something like the image below.<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/marianaggaga.com\/wp-content\/uploads\/2016\/04\/Maptemplate1.png\"><img decoding=\"async\" class=\"alignnone  wp-image-16311\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2016\/04\/Maptemplate1-1024x594.png\" alt=\"Maptemplate\" width=\"788\" height=\"457\" \/><\/a><\/p>\n<p>To achieve the above we created three unordered lists; creating an id attribute for each cloud. As I mentioned earlier we used the encodeURI function to account for the whitespaces in cloud_name so, Azure ACS becomes Azure%20ACS. Let\u2019s look at the code<\/p>\n<pre class=\"brush:xml\"><\/pre>\n<p>JavaScript<\/p>\n<pre class=\"brush:js\">var listoptions = {};\n  \n        function getcloud() {\n           \n            $.ajax({\n                type: \"GET\",\n                url: \"\/cloudcounts\",\n                dataType: \"json\",\n                success: function (cloudinfo) {\n                    console.log(cloudinfo);\n                    $.each(cloudinfo, function (i, entry) {\n                        \/\/changes \"foo bar\" to \"foo%20bar\"\n                        var cloudName = encodeURI(entry.cloud_name);\n                        console.log(cloudName);\n                        if (!listoptions[cloudName]) { listoptions[cloudName] = \"\" };\n                        entry.container = entry.container.replace(\"whereyouat-web\", \"wya-w\");\n                        listoptions[cloudName] += '&lt;li class=\"list-group-item\"&gt;' + '&lt;b&gt;Container:&lt;\/b&gt; ' + entry.container + ' &lt;br&gt;&lt;b&gt;' + entry.Count + '&lt;\/b&gt; PUTs received&lt;\/li&gt;';\n\n                    });\n\n                    for (var prop in listoptions) {\n                        console.log(prop);\n                        \/\/Could use getElementByTagName, but here's how to do it in jQuery as \"#foo\" doens't work with late eval\n                        var listElement = \"ul[id='\" + prop + \"-listview']\";\n                        $(listElement).append(listoptions[prop])\n                    }\n                  \n                },\n\n                error: function (err, status, errortext) {\n                    console.log(errortext);\n                }\n\n            })\n }\n        $().ready(getcloud);<\/pre>\n<p>&nbsp;<\/p>\n<p>HTML<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"brush:xml\">&lt;ul id=\"Azure%20ACS-listview\" data-role=\"listview\" class=\"list-group\"&gt;&lt;\/ul&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Results<\/strong><\/p>\n<p><strong><a href=\"http:\/\/marianaggaga.com\/wp-content\/uploads\/2016\/04\/FinalCounts.png\"><img decoding=\"async\" style=\"padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px\" title=\"FinalCounts\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2016\/04\/FinalCounts_thumb.png\" alt=\"FinalCounts\" width=\"1143\" height=\"440\" border=\"0\" \/><\/a><\/strong><\/p>\n<h2>Summary<\/h2>\n<p>In this and the <a title=\"WhereYouAt  DemoBuild 2016:  Demo UI\" href=\"http:\/\/marianaggaga.com\/ux-demo-flow\/\">previous post, <\/a>I went over <a title=\"WhereYouAt  DemoBuild 2016:  Demo UI\" href=\"http:\/\/marianaggaga.com\/ux-demo-flow\/\">UI requirements<\/a>, and how I constructed it. In series of post entitled &#8220;<a href=\"https:\/\/blogs.msdn.microsoft.com\/webdev\/\">WhereYouAt DemoBuild 2016<\/a>:&#8230;.&#8221; my team is going to cover a variety of topics that include : Load Balancing, traffic managers, and containers. To read these post please visit the .<a href=\"https:\/\/blogs.msdn.microsoft.com\/webdev\/\">Net Web Development and Tools Blog<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my previous post, I went over the user interface and application requirements. Let\u2019s quickly revisit the project requirements: Get coordinates of the users and identify which cloud the ASP.NET Core app is running on. Populate maps with custom pushpins. Display the number of containers running on each cloud.<\/p>\n","protected":false},"author":3344,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197,7509],"tags":[],"class_list":["post-6673","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet","category-aspnetcore"],"acf":[],"blog_post_summary":"<p>In my previous post, I went over the user interface and application requirements. Let\u2019s quickly revisit the project requirements: Get coordinates of the users and identify which cloud the ASP.NET Core app is running on. Populate maps with custom pushpins. Display the number of containers running on each cloud.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/6673","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/3344"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=6673"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/6673\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=6673"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=6673"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=6673"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}