<!DOCTYPE html>
<html>

  <head>
    <link href="//js.arcgis.com/3.13/esri/css/esri.css" rel="stylesheet" data-semver="3.13.0" data-require="arcgis@3.13.0" />
    <link rel="stylesheet" href="style.css" />
  </head>

  <body>
    <div id="map">
      <div id="locationButtons">
        <div id="homeButton"></div>
        <button type="button" title="Geolocate" class="geolocate" id="geolocateButton"></button>
      </div>
    </div>
    <script>
    (function() {
      var root = location.pathname.replace(/\/[^\/]*$/, "");
      var dojoConfig = {
        async: true,
        packages: [{
          name: "geolocate-button",
          location: root,
          main: "geolocate-button"
        }]
      };
      window.dojoConfig = dojoConfig;
    }());
  </script>
    <script src="//js.arcgis.com/3.13/" data-semver="3.13.0" data-require="arcgis@3.13.0"></script>
    <script src="script.js"></script>
  </body>

</html>
require(["esri/map", "geolocate-button"], function(Map, createGeolocateButton) {
  var map;

  map = new Map("map", {
    basemap: "hybrid",
    center: [-120.80566406246835, 47.41322033015946],
    zoom: 7,
    showAttribution: true
  });
  
  createGeolocateButton(document.getElementById("geolocateButton"), map);
});
html, body, #map, .map.container {
    padding:0;
    margin:0;
    height:100%;
}

#locationButtons {
	position: absolute;
	top: 95px;
	left: 20px;
	z-index: 1;
}

button.geolocate {
	width: 34px;
	height: 34px;
	border: none;
	border-radius: 5px;
	background-position: center center;
	background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaBAMAAABbZFH9AAAAIVBMVEX////////09PT19fX09PTz8/Pz8/P09PT09PT09PT09PQZGjmlAAAAC3RSTlMABC00W2mAn9DS6Vd3VDgAAABmSURBVHhetZA7DoAgEEQXPzF2Jl7A2kpvYElpwxW2tuMCNHSW1p7UjaCbuLEiTDHDS8gMAYIwRDL9qjczQ+HtMbw0LlCdDyhHprtI5U7WTnc3Yr1RNiudPsQ3RQsvyHV+mVSOf7kAHRkVQU75GE0AAAAASUVORK5CYII=') /*../images/geolocate.png*/;
	background-repeat: no-repeat;
	background-color: #666;
	background-color: rgba(102,102,102,0.80);
	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
	margin-top: 0.2em;
	cursor: pointer;
}

button.geolocate.busy {
	background-image: url('data:image/gif;base64,R0lGODlhEAAQAPMPAJzNwxSJceDv7L7e13q8rwCAZlirmjaahorEuPD39SSRe2izpEaij6zVzASBaP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAPACwAAAAAEAAQAAAEcfDJl+gydeonlEhFIVCbJBRK4ojJqAkjUiArnEkJM4OOYXymjEDnGLhwQFyicTjiNAiGD1CiJK5RBoNaul6tA8ItqEkgAgxnyzghKABmBEzQoLA5I8Fh0AAI5E8TCQYEDwBUAnAlAgQjhxIDYyUDA1URACH5BAUKAA8ALAAAAAAPABAAAARd8Mn5yJKJTiaVFEGjSUeiOIJSDKMEKAFQcJMRJ8FhFUWWSYbCQTAZEFu01qOxIBBYygfAsFhAox/A6DdpMAxbwQ/BaCQADYH6KNYsBAPzVUPQxiVzDCBzfxyVaiMRACH5BAUKAA8ALAAAAAAQAA8AAARa8Mn5AKJYLslUSkcmOUbSJYaYVEXTNZMwSMTRgAyCHIWAFD1NIBUDAAuzyWCxUhYukoEOIMh8rg2CVsR9wLqUBaLZBRAGiQH6qpIgBPCEgIwBzOAPOfeLz1MiACH5BAUKAA8ALAAAAAAQABAAAARc8MkpAb2SpGeYNAP2HATnLdgmBUMXookgIYvMEADgJVagEqSH6jFQiB4liqyW2AAaDdEiEHCAcgDZZVHoHiihi2AsUAkQluNkkH2M1UJJYtAcHgeyJtwtt8P1GBEAIfkEBQoACAAsAAAAABAADgAABEUQyYkIoVgaWQrP3NYhASgRXgeQmBEMSHFYXhVPRrFh9UrtmMNEgAD4gp1CyXLJlD5DzECWOU6mHSJCa0pmuJQBUAIGRQAAIfkEBQoADgAsAAAAABAAEAAABGvQyenGoNilJhGRhJAlBIcgDqKImbAIpxCg1NCICGARR6UwksQAMUhMEgKD48CSCDiUBANg1AiuVQrAYGAgrtgMQKEILKIYwQGAQTYdTwkwKDAmqoFC0hHIZhoFSg5QaBMKBRcjaQVsGY5+EQAh+QQFCgAPACwAAAAAEAAQAAAEW/DJ+YSgWA4JAM/c1XgAA0pIMj5Mg1nJ0wwWsEjMLQl0tgQGTOKCWbgmiSSosVgEk8pMg3E4EE4TQyOK3TwWMRBhoXgkbodToIB4XHmgxJpIjDsKF8cxbjiEKREAIfkEBQoADgAsAQABAA8ADwAABFbQSSHHkE3qWu9Y2+Zdy+UkpyZQTkM4goFIiYCGxPFu94aYoeCAQMwENR+D7EgrBWusmsKx2xQKCARjOmP4CgSFAuCYhQRXSiBxODYKl8DaoQCqNIZjBAAh+QQFCgAPACwAAAAAEAAQAAAEXfDJ+VKiWN4nhBwbJlwdB4RU4nUJ4mGbZQ2NhAAZDCx4jgEvH0WAKAonAoKy9lEMMK4ho1DoTRgBhMZROHgUgMaC8QAoFhLA03Y41HrBiSLRfhgcPsf3ICHnNko5EQAh+QQFCgAOACwAAAEAEAAPAAAEWtDJ6VKSgmpp5dha922ZJpTACE4NMlxUSanOEtwL2OzDUfwMEADgSpwAAZkEsHK8JonFgSlR1BIKRsOBMDgNBElDBjAwBoEtTHNwmB2E9mZgdTCCNeUGgQBFAAAh+QQFCgAPACwAAAEAEAAPAAAEWPDJSV+qeCZRBcfCRRUFUonJ8A1k8U2CWhFF04mSomfP4AsGRyBAyPgan0SDgbFVDJKXBLFwPg6PIsPgAywkBIBkIBE3CAsBlhdgoh8AJki+gCaKvLIYEwEAIfkEBQoADwAsAAABAA8ADwAABFrwyRGEvPiOorKXRtF8UvcIReEJyWkC45WwGOAMWSshB8MgnplAQFAYgbmhpTUweHAywiPgaSCgTuCCMGwATrDTJDBASBeWh059WDzMjwZhfXG/pY8vKR7DRAAAOw==') /*../images/ajax-loader.gif*/;
	pointer-events: none;
	cursor: default;
}

button.geolocate:hover {
	background-color: #333;
	background-color: rgba(102,102,102,0.90);
}

button.geolocate:active {
	background-color: #ccc;
	background-color: rgba(102,102,102,0.60);
}
ArcGIS JavaScript API: Geolocate Button
=======================================

Creates a Geolocate Button. When the user clicks the button, a popup will appear in the user's current location.

* Displays accuracy in meters or km.
/*global define*/

define([
	"esri/graphic",
	"esri/InfoTemplate",
	"esri/geometry/Point",
	"esri/geometry/Circle",
	"esri/geometry/webMercatorUtils"
], function (Graphic, InfoTemplate, Point, Circle, webMercatorUtils) {
	/**
	 * Creates a geolocate button.
	 * @param {HTMLButtonElement} button
	 * @param {esri/Map} map
	 */
	function createGeolocateButton(button, map) {
		var infoTemplate, nFormat;

		// Setup NumberFormat object if the browser supports it.
		nFormat = (window.Intl && window.Intl.NumberFormat) ? new window.Intl.NumberFormat() : null;

		/**
		 * Formats an amount in meters.
		 * @param {number} m - A number of meters.
		 * @returns {string}
		 */
		function formatMeters(m) {
			var value, unit;
			value = m;
			unit = "meters";

			if (m > 1000) {
				value = m / 1000;
				unit = "km.";
			}

			if (nFormat) { // Make sure browser implements Intl.NumberFormat
				value = nFormat.format(value);
			}
			return [value, unit].join(" ");
		}

		/**
		 * Shows an info window at the given position.
		 * Displays a Circle on the map showing the position accuracy.
		 * @param {external:Position} position
		 */
		function showLocationPopup(position) {
			var pt, attributes, accuracy, circle;

			button.classList.remove("busy");

			accuracy = position.coords.accuracy; // In meters.
			pt = new Point(position.coords.longitude, position.coords.latitude);
			pt = webMercatorUtils.geographicToWebMercator(pt);
			circle = new Circle(pt, {
				radius: accuracy, // Default unit is already meters.
				geodesic: true
			});
			attributes = {
				lat: position.coords.latitude.toFixed(6),
				long: position.coords.longitude.toFixed(6),
				accuracy: formatMeters(accuracy)
			};
			if (map.infoWindow.setFeatures) {
				map.infoWindow.setFeatures([
					new Graphic(circle, null, attributes, infoTemplate)
				]);
				map.infoWindow.show(map.toScreen(pt));
			} else {
				map.infoWindow.setTitle("You are here").setContent(
					["Lat: ", attributes.lat, "<br /> Long:", attributes.long].join()
				).show(map.toScreen(pt));
			}
			map.setExtent(circle.getExtent(), false);
		}

		/**
		 * Shows an error alert message
		 * @param {external:PositionError} error
		 */
		function showLocateError(error) {
			var message = "", strErrorCode;

			button.classList.remove("busy");

			// Check for known errors
			switch (error.code) {
				case error.PERMISSION_DENIED:
					message = "This website does not have permission to use the Geolocation API";
					break;
				case error.POSITION_UNAVAILABLE:
					message = "The current position could not be determined.";
					break;
				case error.PERMISSION_DENIED_TIMEOUT:
					message = "The current position could not be determined within the specified timeout period.";
					break;
			}

			// If it's an unknown error, build a message that includes 
			// information that helps identify the situation so that 
			// the error handler can be updated.
			if (message === "") {
				strErrorCode = error.code.toString();
				message = "The position could not be determined due to an unknown error (Code: " + strErrorCode + ").";
			}
			alert(message);
		}

		/**
		 * Calls the navigator.geolocation.getCurrentPosition function.
		 */
		function geolocate() {
			button.classList.add("busy");
			navigator.geolocation.getCurrentPosition(showLocationPopup, showLocateError, {
				maximumAge: 0,
				timeout: 30000,
				enableHighAccuracy: true
			});
		}

		// This info template is used to format the geocode results in the info window.
		infoTemplate = new InfoTemplate(
			"You are here", [
				"<dl>",
				"<dt>Latitude</dt><dd>${lat}</dd>",
				"<dt>Longitude</dt><dd>${long}</dd>",
				"<dt>Accuracy</dt><dd>±${accuracy}</dd>",
				"</dl>"].join("")
		);

		// If the browser supports geolocation, setup the button.
		// Otherwise, remove the button.
		if (navigator.geolocation) {
			button.onclick = geolocate;
		} else {
			button.disabled = true;
		}
	}

	return createGeolocateButton;
});