diff --git a/css/geolocation-googlegeocoder-widget.css b/css/geolocation-googlegeocoder-widget.css
deleted file mode 100644
index 94a1bf9..0000000
--- a/css/geolocation-googlegeocoder-widget.css
+++ /dev/null
@@ -1,98 +0,0 @@
-
-/**
- * @file
- * CSS for Google Map widget of Geolocation field.
- */
-
-.geolocation-map {
-  /* Clear floated elements */
-  overflow: auto;
-}
-
-.geolocation-map-canvas {
-  height: 350px;
-  width: 100%;
-}
-
-/* Fix Google Maps v3 controls */
-.geolocation-map-canvas .gmnoprint img {
-  max-width: none;
-}
-
-.geocode-controlls-wrapper {
-  display: block;
-  width: 100%;
-  font-size: 14px;
-  margin: 1em 0 0 1em;
-}
-
-.geocode-controlls-wrapper input,
-.geocode-controlls-wrapper button {
-  position: relative;
-  padding: 0;
-  font-size: inherit;
-  height: 32px;
-  outline: none;
-  vertical-align: top;
-  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
-  text-overflow: ellipsis;
-  border: 1px solid transparent;
-  -webkit-box-sizing: content-box;
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
-  -webkit-appearance: none;
-  -moz-appearance: none;
-  appearance: none;
-}
-
-.geocode-controlls-wrapper input {
-  padding: 0 1em;
-  border-radius: 2px 0 0 2px;
-  background-color: #fff;
-  width: 40%;
-  max-width: 350px;
-  z-index: 2;
-}
-.geocode-controlls-wrapper input:focus {
-  border-color: #4d90fe;
-}
-
-.geocode-controlls-wrapper button {
-  color: #FFF;
-  cursor: pointer;
-  height: 32px;
-  text-align: center;
-}
-
-button.submit {
-  background-color: #4d90fe;
-  background-image: -webkit-linear-gradient(top,#4d90fe,#4787ed);
-  border-radius: 0 2px 2px 0;
-  width: 72px;
-}
-button.submit::before {
-  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAABVUlEQVRYw+2YQRGEMAxFkVAJlYAEJCABCUhAQiWshJWABCRUAg7+XsrMTkibNDBdDvtnek0fSfqToQPQPeE8AuK5IDkBGAC8AESctQEIAHxXKTUIgB7ACr0CAHcrCIAJNm0A+ltALkAc2jWlKoKkcnCKCdCR0i3p4lNmroJwPRGEgC6VhGo2gaTXUQUhwEQryKsmUOaZU40WEOoTk8Eb3iTGYgGhcgaQmcRYL4N0BjHl+RnIeDuI1iFJ8EBivC0gm7bRCsGj1ktKIIGx6pohNjNZ9RYQnxliTgHRM1a/XrH4kIEZhEzstT0mgeTmBpJZzemJjgk65naTO9aAPvOFtavAWMqKdjHyhcxIW9quGRVVO2uh/lTr8fWMqbEw1cvzV/AlXXico2c884IgwZhADMY2STBNQDQwzUAkmKYgAoxvClKAGZqDMDBb89IwRjlI0/f/W+ID3tQLQPib2qQAAAAASUVORK5CYII=);
-  background-size: 17px;
-  content: "";
-  display: block;
-  height: 17px;
-  margin: 0 auto;
-  width: 17px;
-}
-
-button.clear {
-  margin: 0 0.5em;
-  background-color: #736648;
-  background-image: -webkit-linear-gradient(top,#736648,#685C41);
-  border-radius: 2px;
-  width: 36px;
-}
-button.clear::before {
-  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAA3CAYAAACo29JGAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3MEEyNTM1QjBBMjA2ODExODA4MzkzODI3MjczQzA3MCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoyNzhDRDg3QTQ5MEExMUU0QTdGMkM1NzMyMDlBMjJBNSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyNzhDRDg3OTQ5MEExMUU0QTdGMkM1NzMyMDlBMjJBNSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NzBBMjUzNUIwQTIwNjgxMTgwODM5MzgyNzI3M0MwNzAiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NzBBMjUzNUIwQTIwNjgxMTgwODM5MzgyNzI3M0MwNzAiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5jChSGAAAB2UlEQVR42tTaS07DQAwG4JANCSu4AuIstN3BJWFJyYaUy3ACRFclrAYPZKRplMfMxPbYln5VSh3JX9W6UZTCGFN42UL2kGpwXHou+7m3/vEh7Nv8V6sIaGFv/dydD3QNGw9mFAF9mBkCp2AagGOwM6BtejXzJRE4B3PV2MYaclAEDIFZz5U7QQuwCoUNt6V0YBRsiHPAViAwGjaGkwhMgk3hJAGTYXM4CcBVsCVcDLCWBgvB5QCiwEJxnEA0WAyOA4gKi8VRAtFhKTgKIAksFYcJJIOtwWEASWFrcWuA5DAMXAqQBYaFiwHecMEwcaHALy6YzcWfEK8qyB6ySTj3HfIIOWENUxa41UEeIIfcMApcCpAEZgv7a+nXNeSjf52qI+QO8kkxQEkEs7+95wWY+wCeILUWnIW9QLaB/ff9Eqql42JhpMCSGXbkBJaMMLsVbxe2KC6Q8Z6Hf23ZRvRnu/yKhRWcwBwwNmAuGAswJ4wcmBtGCpQAIwNKgZEAJcHQgdJgqMBsa5oDKBWGModk2Op5pMNWzaUBljyfFljSnJpg0cCQp/YkwWKAjXtCtlMECwFaz8417kaAkmFzwK73nG1LH6gBNgb8cbCx/zn7RqMI5gMbH2bzK8AAUThtyVYr9bAAAAAASUVORK5CYII=);
-  background-size: 12px;
-  content: "";
-  display: block;
-  height: 12px;
-  margin: 0 auto;
-  width: 12px;
-}
diff --git a/css/geolocation-html5-widget.css b/css/geolocation-html5-widget.css
deleted file mode 100644
index 0d14952..0000000
--- a/css/geolocation-html5-widget.css
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * @file
- * CSS for the HTML5 geolocation widget of Geolocation field.
- */
-
-.geolocation-html5-button {
-  padding: 0 0.75em 0 3.5em;
-  position: relative;
-  background-color: #eee;
-  width: 100%;
-  min-height: 34px;
-  line-height: 34px;
-  cursor: pointer;
-  border: 0;
-  border-radius: 2px;
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  box-sizing: border-box;
-}
-
-.geolocation-html5-button.disabled {
-  cursor: default;
-}
-
-/**
- * Location icon by: http://jxnblk.github.io/
- */
-.geolocation-html5-button::before {
-  background: url(data:image/png;base64,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) no-repeat scroll center center transparent;
-  background-size: 20px;
-  height: 20px;
-  width: 20px;
-  content: "";
-  display: block;
-  position: absolute;
-  top: 0.55em;
-  left: 1em;
-  opacity: 0.4;
-}
-
-.geolocation-html5-button .clear,
-.geolocation-html5-button .search {
-  border-radius: 0 2px 2px 0;
-  height: 100%;
-  width: 40px;
-  position: absolute;
-  top: 0;
-  right: 0;
-  cursor: pointer;
-}
-
-.geolocation-html5-button .clear {
-  display: none;
-  background-color: #736648;
-  background-image: -webkit-linear-gradient(top,#736648,#685C41);
-  z-index: 10;
-}
-.geolocation-html5-button .clear::after {
-  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAA3CAYAAACo29JGAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3MEEyNTM1QjBBMjA2ODExODA4MzkzODI3MjczQzA3MCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoyNzhDRDg3QTQ5MEExMUU0QTdGMkM1NzMyMDlBMjJBNSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyNzhDRDg3OTQ5MEExMUU0QTdGMkM1NzMyMDlBMjJBNSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NzBBMjUzNUIwQTIwNjgxMTgwODM5MzgyNzI3M0MwNzAiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NzBBMjUzNUIwQTIwNjgxMTgwODM5MzgyNzI3M0MwNzAiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5jChSGAAAB2UlEQVR42tTaS07DQAwG4JANCSu4AuIstN3BJWFJyYaUy3ACRFclrAYPZKRplMfMxPbYln5VSh3JX9W6UZTCGFN42UL2kGpwXHou+7m3/vEh7Nv8V6sIaGFv/dydD3QNGw9mFAF9mBkCp2AagGOwM6BtejXzJRE4B3PV2MYaclAEDIFZz5U7QQuwCoUNt6V0YBRsiHPAViAwGjaGkwhMgk3hJAGTYXM4CcBVsCVcDLCWBgvB5QCiwEJxnEA0WAyOA4gKi8VRAtFhKTgKIAksFYcJJIOtwWEASWFrcWuA5DAMXAqQBYaFiwHecMEwcaHALy6YzcWfEK8qyB6ySTj3HfIIOWENUxa41UEeIIfcMApcCpAEZgv7a+nXNeSjf52qI+QO8kkxQEkEs7+95wWY+wCeILUWnIW9QLaB/ff9Eqql42JhpMCSGXbkBJaMMLsVbxe2KC6Q8Z6Hf23ZRvRnu/yKhRWcwBwwNmAuGAswJ4wcmBtGCpQAIwNKgZEAJcHQgdJgqMBsa5oDKBWGModk2Op5pMNWzaUBljyfFljSnJpg0cCQp/YkwWKAjXtCtlMECwFaz8417kaAkmFzwK73nG1LH6gBNgb8cbCx/zn7RqMI5gMbH2bzK8AAUThtyVYr9bAAAAAASUVORK5CYII=) no-repeat center center transparent;
-  background-size: 12px;
-  content: "";
-  display: block;
-  height: 100%;
-}
-
-.geolocation-html5-button .search {
-  background-color: #4d90fe;
-  background-image: -webkit-linear-gradient(top,#4d90fe,#4787ed);
-}
-.geolocation-html5-button .search::before {
-  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAABVUlEQVRYw+2YQRGEMAxFkVAJlYAEJCABCUhAQiWshJWABCRUAg7+XsrMTkibNDBdDvtnek0fSfqToQPQPeE8AuK5IDkBGAC8AESctQEIAHxXKTUIgB7ACr0CAHcrCIAJNm0A+ltALkAc2jWlKoKkcnCKCdCR0i3p4lNmroJwPRGEgC6VhGo2gaTXUQUhwEQryKsmUOaZU40WEOoTk8Eb3iTGYgGhcgaQmcRYL4N0BjHl+RnIeDuI1iFJ8EBivC0gm7bRCsGj1ktKIIGx6pohNjNZ9RYQnxliTgHRM1a/XrH4kIEZhEzstT0mgeTmBpJZzemJjgk65naTO9aAPvOFtavAWMqKdjHyhcxIW9quGRVVO2uh/lTr8fWMqbEw1cvzV/AlXXico2c884IgwZhADMY2STBNQDQwzUAkmKYgAoxvClKAGZqDMDBb89IwRjlI0/f/W+ID3tQLQPib2qQAAAAASUVORK5CYII=) no-repeat center center transparent;
-  background-size: 17px;
-  content: "";
-  display: block;
-  height: 100%;
-}
diff --git a/css/geolocation-widget-googlegeocoder.css b/css/geolocation-widget-googlegeocoder.css
new file mode 100644
index 0000000..9351c8f
--- /dev/null
+++ b/css/geolocation-widget-googlegeocoder.css
@@ -0,0 +1,120 @@
+
+/**
+ * @file
+ * CSS for Google Map widget of Geolocation field.
+ */
+
+.geolocation-map {
+  /* Clear floated elements */
+  overflow: auto;
+}
+
+.geolocation-map-canvas {
+  height: 350px;
+  width: 100%;
+}
+
+/* Fix Google Maps v3 controls */
+.geolocation-map-canvas .gmnoprint img {
+  max-width: none;
+}
+
+.geocode-controlls-wrapper {
+  display: block;
+  width: 100%;
+  font-size: 14px;
+  margin: 1em 0 0 1em;
+}
+
+.geocode-controlls-wrapper input,
+.geocode-controlls-wrapper button {
+  position: relative;
+  padding: 0;
+  font-size: inherit;
+  height: 32px;
+  outline: none;
+  vertical-align: top;
+  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
+  text-overflow: ellipsis;
+  border: 1px solid transparent;
+  -webkit-box-sizing: content-box;
+  -moz-box-sizing: content-box;
+  box-sizing: content-box;
+  -webkit-appearance: none;
+  -moz-appearance: none;
+  appearance: none;
+}
+
+.geocode-controlls-wrapper input {
+  padding: 0 1em;
+  border-radius: 2px 0 0 2px;
+  background-color: #fff;
+  width: 40%;
+  max-width: 350px;
+  z-index: 3;
+}
+.geocode-controlls-wrapper input:focus {
+  border-color: #4d90fe;
+}
+
+.geocode-controlls-wrapper button {
+  color: #FFF;
+  cursor: pointer;
+  height: 32px;
+  text-align: center;
+  z-index: 2;
+}
+
+.geocode-controlls-wrapper .geolocation-map-indicator {
+  z-index: 1;
+  position: relative;
+  background-color: rgba(174, 213, 129, 0.75);
+  -webkit-transition: all 0.5s ease;
+  -moz-transition: all 0.5s ease;
+  -o-transition: all 0.5s ease;
+  transition: all 0.5s ease;
+  text-align: right;
+  margin-left: 10%;
+  width: 40%;
+  border-radius: 0px 0px 2px 2px;
+  padding: 0px 2%;
+  top: -20px;
+  color: rgb(255,255,255);
+}
+.geocode-controlls-wrapper .geolocation-map-indicator.has-location {
+  top: 0px;
+  box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.3);
+}
+
+button.submit {
+  background-color: #4d90fe;
+  background-image: -webkit-linear-gradient(top,#4d90fe,#4787ed);
+  border-radius: 0 2px 2px 0;
+  width: 72px;
+}
+button.submit::before {
+  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAABVUlEQVRYw+2YQRGEMAxFkVAJlYAEJCABCUhAQiWshJWABCRUAg7+XsrMTkibNDBdDvtnek0fSfqToQPQPeE8AuK5IDkBGAC8AESctQEIAHxXKTUIgB7ACr0CAHcrCIAJNm0A+ltALkAc2jWlKoKkcnCKCdCR0i3p4lNmroJwPRGEgC6VhGo2gaTXUQUhwEQryKsmUOaZU40WEOoTk8Eb3iTGYgGhcgaQmcRYL4N0BjHl+RnIeDuI1iFJ8EBivC0gm7bRCsGj1ktKIIGx6pohNjNZ9RYQnxliTgHRM1a/XrH4kIEZhEzstT0mgeTmBpJZzemJjgk65naTO9aAPvOFtavAWMqKdjHyhcxIW9quGRVVO2uh/lTr8fWMqbEw1cvzV/AlXXico2c884IgwZhADMY2STBNQDQwzUAkmKYgAoxvClKAGZqDMDBb89IwRjlI0/f/W+ID3tQLQPib2qQAAAAASUVORK5CYII=);
+  background-size: 17px;
+  content: "";
+  display: block;
+  height: 17px;
+  margin: 0 auto;
+  width: 17px;
+}
+
+button.clear {
+  margin: 0 0.5em;
+  background-color: #736648;
+  background-image: -webkit-linear-gradient(top,#736648,#685C41);
+  border-radius: 2px;
+  width: 36px;
+}
+button.clear::before {
+  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAA3CAYAAACo29JGAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3MEEyNTM1QjBBMjA2ODExODA4MzkzODI3MjczQzA3MCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoyNzhDRDg3QTQ5MEExMUU0QTdGMkM1NzMyMDlBMjJBNSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyNzhDRDg3OTQ5MEExMUU0QTdGMkM1NzMyMDlBMjJBNSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NzBBMjUzNUIwQTIwNjgxMTgwODM5MzgyNzI3M0MwNzAiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NzBBMjUzNUIwQTIwNjgxMTgwODM5MzgyNzI3M0MwNzAiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5jChSGAAAB2UlEQVR42tTaS07DQAwG4JANCSu4AuIstN3BJWFJyYaUy3ACRFclrAYPZKRplMfMxPbYln5VSh3JX9W6UZTCGFN42UL2kGpwXHou+7m3/vEh7Nv8V6sIaGFv/dydD3QNGw9mFAF9mBkCp2AagGOwM6BtejXzJRE4B3PV2MYaclAEDIFZz5U7QQuwCoUNt6V0YBRsiHPAViAwGjaGkwhMgk3hJAGTYXM4CcBVsCVcDLCWBgvB5QCiwEJxnEA0WAyOA4gKi8VRAtFhKTgKIAksFYcJJIOtwWEASWFrcWuA5DAMXAqQBYaFiwHecMEwcaHALy6YzcWfEK8qyB6ySTj3HfIIOWENUxa41UEeIIfcMApcCpAEZgv7a+nXNeSjf52qI+QO8kkxQEkEs7+95wWY+wCeILUWnIW9QLaB/ff9Eqql42JhpMCSGXbkBJaMMLsVbxe2KC6Q8Z6Hf23ZRvRnu/yKhRWcwBwwNmAuGAswJ4wcmBtGCpQAIwNKgZEAJcHQgdJgqMBsa5oDKBWGModk2Op5pMNWzaUBljyfFljSnJpg0cCQp/YkwWKAjXtCtlMECwFaz8417kaAkmFzwK73nG1LH6gBNgb8cbCx/zn7RqMI5gMbH2bzK8AAUThtyVYr9bAAAAAASUVORK5CYII=);
+  background-size: 12px;
+  content: "";
+  display: block;
+  height: 12px;
+  margin: 0 auto;
+  width: 12px;
+}
diff --git a/css/geolocation-widget-html5.css b/css/geolocation-widget-html5.css
new file mode 100644
index 0000000..0d14952
--- /dev/null
+++ b/css/geolocation-widget-html5.css
@@ -0,0 +1,76 @@
+/**
+ * @file
+ * CSS for the HTML5 geolocation widget of Geolocation field.
+ */
+
+.geolocation-html5-button {
+  padding: 0 0.75em 0 3.5em;
+  position: relative;
+  background-color: #eee;
+  width: 100%;
+  min-height: 34px;
+  line-height: 34px;
+  cursor: pointer;
+  border: 0;
+  border-radius: 2px;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+
+.geolocation-html5-button.disabled {
+  cursor: default;
+}
+
+/**
+ * Location icon by: http://jxnblk.github.io/
+ */
+.geolocation-html5-button::before {
+  background: url(data:image/png;base64,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) no-repeat scroll center center transparent;
+  background-size: 20px;
+  height: 20px;
+  width: 20px;
+  content: "";
+  display: block;
+  position: absolute;
+  top: 0.55em;
+  left: 1em;
+  opacity: 0.4;
+}
+
+.geolocation-html5-button .clear,
+.geolocation-html5-button .search {
+  border-radius: 0 2px 2px 0;
+  height: 100%;
+  width: 40px;
+  position: absolute;
+  top: 0;
+  right: 0;
+  cursor: pointer;
+}
+
+.geolocation-html5-button .clear {
+  display: none;
+  background-color: #736648;
+  background-image: -webkit-linear-gradient(top,#736648,#685C41);
+  z-index: 10;
+}
+.geolocation-html5-button .clear::after {
+  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAA3CAYAAACo29JGAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3MEEyNTM1QjBBMjA2ODExODA4MzkzODI3MjczQzA3MCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoyNzhDRDg3QTQ5MEExMUU0QTdGMkM1NzMyMDlBMjJBNSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyNzhDRDg3OTQ5MEExMUU0QTdGMkM1NzMyMDlBMjJBNSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NzBBMjUzNUIwQTIwNjgxMTgwODM5MzgyNzI3M0MwNzAiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NzBBMjUzNUIwQTIwNjgxMTgwODM5MzgyNzI3M0MwNzAiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5jChSGAAAB2UlEQVR42tTaS07DQAwG4JANCSu4AuIstN3BJWFJyYaUy3ACRFclrAYPZKRplMfMxPbYln5VSh3JX9W6UZTCGFN42UL2kGpwXHou+7m3/vEh7Nv8V6sIaGFv/dydD3QNGw9mFAF9mBkCp2AagGOwM6BtejXzJRE4B3PV2MYaclAEDIFZz5U7QQuwCoUNt6V0YBRsiHPAViAwGjaGkwhMgk3hJAGTYXM4CcBVsCVcDLCWBgvB5QCiwEJxnEA0WAyOA4gKi8VRAtFhKTgKIAksFYcJJIOtwWEASWFrcWuA5DAMXAqQBYaFiwHecMEwcaHALy6YzcWfEK8qyB6ySTj3HfIIOWENUxa41UEeIIfcMApcCpAEZgv7a+nXNeSjf52qI+QO8kkxQEkEs7+95wWY+wCeILUWnIW9QLaB/ff9Eqql42JhpMCSGXbkBJaMMLsVbxe2KC6Q8Z6Hf23ZRvRnu/yKhRWcwBwwNmAuGAswJ4wcmBtGCpQAIwNKgZEAJcHQgdJgqMBsa5oDKBWGModk2Op5pMNWzaUBljyfFljSnJpg0cCQp/YkwWKAjXtCtlMECwFaz8417kaAkmFzwK73nG1LH6gBNgb8cbCx/zn7RqMI5gMbH2bzK8AAUThtyVYr9bAAAAAASUVORK5CYII=) no-repeat center center transparent;
+  background-size: 12px;
+  content: "";
+  display: block;
+  height: 100%;
+}
+
+.geolocation-html5-button .search {
+  background-color: #4d90fe;
+  background-image: -webkit-linear-gradient(top,#4d90fe,#4787ed);
+}
+.geolocation-html5-button .search::before {
+  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAABVUlEQVRYw+2YQRGEMAxFkVAJlYAEJCABCUhAQiWshJWABCRUAg7+XsrMTkibNDBdDvtnek0fSfqToQPQPeE8AuK5IDkBGAC8AESctQEIAHxXKTUIgB7ACr0CAHcrCIAJNm0A+ltALkAc2jWlKoKkcnCKCdCR0i3p4lNmroJwPRGEgC6VhGo2gaTXUQUhwEQryKsmUOaZU40WEOoTk8Eb3iTGYgGhcgaQmcRYL4N0BjHl+RnIeDuI1iFJ8EBivC0gm7bRCsGj1ktKIIGx6pohNjNZ9RYQnxliTgHRM1a/XrH4kIEZhEzstT0mgeTmBpJZzemJjgk65naTO9aAPvOFtavAWMqKdjHyhcxIW9quGRVVO2uh/lTr8fWMqbEw1cvzV/AlXXico2c884IgwZhADMY2STBNQDQwzUAkmKYgAoxvClKAGZqDMDBb89IwRjlI0/f/W+ID3tQLQPib2qQAAAAASUVORK5CYII=) no-repeat center center transparent;
+  background-size: 17px;
+  content: "";
+  display: block;
+  height: 100%;
+}
diff --git a/geolocation.libraries.yml b/geolocation.libraries.yml
index 0276eee..aaadc3b 100644
--- a/geolocation.libraries.yml
+++ b/geolocation.libraries.yml
@@ -1,24 +1,37 @@
+# Geolocation core library.
+geolocation.core:
+  version: 8.x-1.x
+  dependencies:
+    - core/drupal
+    - core/jquery
+    - core/underscore
+    - core/drupalSettings
+  js:
+    js/geolocation.js: {}
+# Google maps display formatter.
+geolocation.maps:
+  version: 8.x-1.x
+  js:
+    js/geolocation-formatter-googlemap.js: {}
+  dependencies:
+    - geolocation/geolocation.core
+# Google geocoder widget library.
 geolocation.widgets.googlegeocoder:
   version: 1.x
   css:
     theme:
-      css/geolocation-googlegeocoder-widget.css: {}
+      css/geolocation-widget-googlegeocoder.css: {}
   js:
-    //maps.googleapis.com/maps/api/js?libraries=places: { type: external }
-    js/geolocation-googlegeocoder-widget.js: { scope: footer }
+    js/geolocation-widget-googlegeocoder.js: { scope: footer }
   dependencies:
-    - core/jquery
-    - core/drupal
-    - core/drupalSettings
-    - core/jquery.once
+    - geolocation/geolocation.core
+# HTML5 widget library.
 geolocation.widgets.html5:
   version: 1.x
   css:
     theme:
-      css/geolocation-html5-widget.css: {}
+      css/geolocation-widget-html5.css: {}
   js:
-    js/geolocation-html5-widget.js: { scope: footer }
+    js/geolocation-widget-html5.js: { scope: footer }
   dependencies:
-    - core/jquery
-    - core/drupal
-    - core/drupalSettings
+    - geolocation/geolocation.core
diff --git a/js/geolocation-formatter-googlemap.js b/js/geolocation-formatter-googlemap.js
new file mode 100644
index 0000000..7b2ecf5
--- /dev/null
+++ b/js/geolocation-formatter-googlemap.js
@@ -0,0 +1,44 @@
+/**
+ * @file
+ * Javascript for the geocoder Google map formatter.
+ */
+(function ($, Drupal) {
+  // Ensure and use shortcut for gwolocation.
+  var geolocation = Drupal.geolocation = Drupal.geolocation || {};
+
+  Drupal.behaviors.geolocationGoogleMaps = {
+    attach: function (context, settings) {
+      // Ensure itterables.
+      settings.geolocation = settings.geolocation || {maps: []};
+      // Make sure the lazy loader is available.
+      if (typeof Drupal.geolocation.load_google === 'function') {
+        // First load the library from google.
+        Drupal.geolocation.load_google(function(){
+
+          initialize(settings.geolocation.maps);
+        });
+      }
+    }
+  };
+
+  function initialize(maps) {
+    // Loop though all objects and add maps to the page.
+    $.each(maps, function(delta, map) {
+      // Get the container object.
+      map.container = document.getElementById(map.id);
+
+      if ($(map.container).length >= 1
+        && !$(map.container).hasClass('geolocation-processed')
+        && typeof google !== 'undefined'
+        && typeof google.maps !== 'undefined'
+      ) {
+        // Add any missing settings.
+        map.settings = $.extend(geolocation.default_settings(), map.settings);
+        // Add the map by ID with settings.
+        geolocation.add_map(map);
+        // Set the already processed flag.
+        $(map.container).addClass('geolocation-processed');
+      }
+    });
+  }
+})(jQuery, Drupal);
diff --git a/js/geolocation-googlegeocoder-widget.js b/js/geolocation-googlegeocoder-widget.js
deleted file mode 100644
index b292f2e..0000000
--- a/js/geolocation-googlegeocoder-widget.js
+++ /dev/null
@@ -1,285 +0,0 @@
-/**
- * @file
- * Javascript for the Google geocoder widget.
- */
-
-(function ($, Drupal, drupalSettings) {
-  "use strict";
-
-  Drupal.geolocation = Drupal.geolocation || {};
-  Drupal.geolocation.maps = Drupal.geolocation.maps || {};
-  Drupal.geolocation.markers = Drupal.geolocation.markers || {};
-  Drupal.geolocation.geocoders = Drupal.geolocation.geocoder || {};
-  Drupal.geolocation.geocodeControls = Drupal.geolocation.geocodeControls || {};
-
-  Drupal.behaviors.geolocationGooglemaps = {
-    attach: function(context, settings) {
-
-      var lat;
-      var lng;
-      var latLng;
-      var mapOptions;
-      var singleClick;
-
-      /**
-       * Process drupalSettings for every Google map present on the current page.
-       */
-      $.each(drupalSettings.geolocation.defaults, function(canvasId, mapDefaults) {
-
-        // Process every map canvas once. This will also add 'map-canvas-processed' class.
-        $("#" + canvasId).once().each(function() {
-
-          var $mapCanvas = $(this);
-          var $hiddenLat = $mapCanvas.siblings(".geolocation-hidden-lat");
-          var $hiddenLng = $mapCanvas.siblings(".geolocation-hidden-lng");
-
-          var hiddenLatValue = $hiddenLat.attr('value');
-          var hiddenLngValue = $hiddenLng.attr('value');
-          lat = hiddenLatValue == false ? mapDefaults.lat : hiddenLatValue;
-          lng = hiddenLngValue == false ? mapDefaults.lng : hiddenLngValue;
-          latLng = new google.maps.LatLng(lat, lng);
-
-          // Set map options
-          mapOptions = {
-            scrollwheel: false,
-            panControl: false,
-            mapTypeControl: true,
-            scaleControl: false,
-            streetViewControl: false,
-            overviewMapControl: false,
-            zoomControl: true,
-            zoomControlOptions: {
-              style: google.maps.ZoomControlStyle.SMALL,
-              position: google.maps.ControlPosition.LEFT_BOTTOM
-            },
-            mapTypeId: google.maps.MapTypeId.ROADMAP,
-            center: latLng,
-            zoom: 2,
-          }
-
-          // Create map
-          Drupal.geolocation.maps[canvasId] = new google.maps.Map(document.getElementById(canvasId), mapOptions);
-
-          // Create geocoder
-          Drupal.geolocation.geocoders[canvasId] = new google.maps.Geocoder();
-
-          // Create control elements
-          Drupal.geolocation.geocodeControls[canvasId] = new GeocodeControl(Drupal.geolocation.maps[canvasId]);
-          Drupal.geolocation.geocodeControls[canvasId].index = 1;
-          Drupal.geolocation.maps[canvasId].controls[google.maps.ControlPosition.LEFT_TOP].push(Drupal.geolocation.geocodeControls[canvasId]);
-
-          // Set initial marker
-          if (lat && lng) {
-            Drupal.geolocation.codeLatLng(latLng, $mapCanvas, 'initialize');
-          }
-
-          // Listener to set marker
-          google.maps.event.addListener(Drupal.geolocation.maps[canvasId], 'click', function(marker) {
-            var $mapCanvas = $('#' + canvasId);
-            // Create 300ms timeout to wait for double click.
-            singleClick = setTimeout(function() {
-              Drupal.geolocation.codeLatLng(marker.latLng, $mapCanvas, 'marker');
-              Drupal.geolocation.setMapMarker(marker.latLng, $mapCanvas);
-            }, 300);
-          });
-
-          // Detect double click to avoid setting marker
-          google.maps.event.addListener(Drupal.geolocation.maps[canvasId], 'dblclick', function(me) {
-            clearTimeout(singleClick);
-          });
-        })
-
-      });
-
-      /**
-       * Click event handler to the 'Get location' button.
-       */
-      $('.geolocation-map-canvas').on('click', '.geocode-controlls-wrapper .submit', function(event) {
-        var $mapCanvas = $(this).closest('.geolocation-map-canvas');
-        event.preventDefault();
-        Drupal.geolocation.codeAddress($mapCanvas);
-      });
-
-      /**
-       * Keypress event handler for the ENTER key to the geocoder input field.
-       */
-      $('.geolocation-map-canvas').on('keypress', '.geocode-controlls-wrapper .input', function(event){
-        if (event.which == 13) {
-          var $mapCanvas = $(this).closest('.geolocation-map-canvas');
-          event.preventDefault();
-          Drupal.geolocation.codeAddress($mapCanvas);
-        }
-      });
-
-      /**
-       * Click event handler to the 'Get location' button.
-       */
-      $('.geolocation-map-canvas').on('click', '.geocode-controlls-wrapper .clear', function(event) {
-        var $mapCanvas = $(this).closest('.geolocation-map-canvas');
-        event.preventDefault();
-        Drupal.geolocation.clearLocation($mapCanvas);
-      });
-
-    }
-  };
-
-  /**
-   * Geocode location from address field input.
-   *
-   * @param $mapCanvas
-   *   jQuery object containing the parent map canvas
-   */
-  Drupal.geolocation.codeAddress = function($mapCanvas) {
-    var canvasId = $mapCanvas.attr('id');
-    var $addressInput = $('.geocode-controlls-wrapper .input', $mapCanvas);
-    var address = $addressInput.val();
-
-    // Return if the input field is empty.
-    if (address.length < 1) {
-      return;
-    }
-
-    Drupal.geolocation.geocoders[canvasId].geocode( { 'address': address }, function(results, status) {
-      if (status == google.maps.GeocoderStatus.OK) {
-        Drupal.geolocation.maps[canvasId].fitBounds(results[0].geometry.viewport);
-        Drupal.geolocation.codeLatLng(results[0].geometry.location, $mapCanvas, 'textinput');
-      }
-      else {
-        alert(Drupal.t('Geocode was not successful for the following reason: ') + status);
-      }
-    });
-  }
-
-  /**
-   * Set the latitude and longitude values to the input fields
-   * And optionally update the address field
-   *
-   * @param latLng
-   *   a location (latLng) object from google maps api
-   * @param $mapCanvas
-   *   jQuery object containing the parent map canvas
-   * @param op
-   *   the op that was performed
-   */
-  Drupal.geolocation.codeLatLng = function(latLng, $mapCanvas, op) {
-    var canvasId = $mapCanvas.attr('id');
-    var $hiddenLat = $mapCanvas.siblings(".geolocation-hidden-lat");
-    var $hiddenLng = $mapCanvas.siblings(".geolocation-hidden-lng");
-    var $addressInput = $('.geocode-controlls-wrapper .input', $mapCanvas);
-    var lat = latLng.lat();
-    var lng = latLng.lng();
-
-    // Update the lat and lng input fields
-    $hiddenLat.attr('value', lat);
-    $hiddenLng.attr('value', lng);
-
-    // Return if there is no geocoder registered for the current map canvasId.
-    if (!Drupal.geolocation.geocoders[canvasId]) {
-      return;
-    }
-
-    // Update the address field
-    if (op == 'marker' || op == 'initialize') {
-      Drupal.geolocation.geocoders[canvasId].geocode({'latLng': latLng}, function(results, status) {
-        if (status == google.maps.GeocoderStatus.OK) {
-          $addressInput.val(results[0].formatted_address);
-          // When initializing the map also set a marker and zoom in.
-          if (op == 'initialize') {
-            Drupal.geolocation.setMapMarker(results[0].geometry.location, $mapCanvas);
-            Drupal.geolocation.maps[canvasId].fitBounds(results[0].geometry.viewport);
-          }
-        }
-        else {
-          $addressInput.val('');
-          // Why throw an error, the geocoder just didnt return an adress
-          //if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
-          //  alert(Drupal.t('Geocoder failed due to: ') + status);
-          //}
-        }
-      });
-    }
-    else if (op == 'textinput') {
-      // Set a marker on textinput
-      Drupal.geolocation.setMapMarker(latLng, $mapCanvas);
-    }
-
-    return false;
-  }
-
-  /**
-   * Set/Update a marker on a map
-   *
-   * @param latLng
-   *   a location (latLng) object from google maps api
-   * @param $mapCanvas
-   *   jQuery object containing the parent map canvas
-   */
-  Drupal.geolocation.setMapMarker = function(latLng, $mapCanvas) {
-    var canvasId = $mapCanvas.attr('id');
-
-    // Remove old marker
-    if (Drupal.geolocation.markers[canvasId]) {
-      Drupal.geolocation.markers[canvasId].setMap(null);
-    }
-    Drupal.geolocation.markers[canvasId] = new google.maps.Marker({
-      map: Drupal.geolocation.maps[canvasId],
-      // draggable: true,
-      position: latLng
-    });
-    Drupal.geolocation.maps[canvasId].panTo(latLng);
-
-    google.maps.event.addListener(Drupal.geolocation.markers[canvasId], 'dragend', function(marker) {
-      Drupal.geolocation.codeLatLng(marker.latLng, $parent, 'marker');
-    });
-  }
-
-  /**
-   * Clear/Remove the values and the marker
-   *
-   * @param $mapCanvas
-   *   jQuery object containing the parent map canvas
-   */
-  Drupal.geolocation.clearLocation = function($mapCanvas) {
-    var canvasId = $mapCanvas.attr('id');
-
-    $mapCanvas.siblings(".geolocation-hidden-lat").val('');
-    $mapCanvas.siblings(".geolocation-hidden-lng").val('');
-    $('.geocode-controlls-wrapper .input', $mapCanvas).val('');
-
-    Drupal.geolocation.markers[canvasId].setMap();
-    var latLng = new google.maps.LatLng(0, 0);
-    Drupal.geolocation.maps[canvasId].setCenter(latLng);
-    Drupal.geolocation.maps[canvasId].setZoom(2);
-  }
-
-  /**
-   * GeocodeControl is a constructor that adds custom geocoder controls to the map.
-   * @constructor
-   */
-  function GeocodeControl() {
-
-    // Create wrapper DIV
-    var controlDiv = document.createElement('div');
-    controlDiv.className = 'geocode-controlls-wrapper';
-
-    // Create location input
-    var controlInput = document.createElement('input');
-    controlInput.setAttribute('type', 'text');
-    controlInput.className = 'input';
-    controlInput.placeholder = 'Enter a location';
-    controlDiv.appendChild(controlInput);
-
-    // Create submit button
-    var controlSubmit = document.createElement('button');
-    controlSubmit.className = 'submit';
-    controlDiv.appendChild(controlSubmit);
-
-    // Create clear button
-    var controlClear = document.createElement('button');
-    controlClear.className = 'clear';
-    controlDiv.appendChild(controlClear);
-
-    return controlDiv;
-  }
-
-})(jQuery, Drupal, drupalSettings);
diff --git a/js/geolocation-html5-widget.js b/js/geolocation-html5-widget.js
deleted file mode 100644
index df5963e..0000000
--- a/js/geolocation-html5-widget.js
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * @file
- * Javascript for the Geolocation HTML5 widget.
- */
-
-(function ($, Drupal, navigator) {
-  "use strict";
-
-
-  Drupal.behaviors.geolocationHTML5 = {
-    attach: function(context, settings) {
-
-      $('.geolocation-html5-button:not(.disabled)').each( function(index) {
-        // The parent element.
-        var $thisButton = $(this);
-
-        // Set the values of hidden form inputs.
-        var latDefault = $thisButton.siblings(".geolocation-hidden-lat").val();
-        var lngDefault = $thisButton.siblings(".geolocation-hidden-lng").val();
-
-        if (latDefault.length > 1 && lngDefault.length > 1) {
-          // Hide the default text.
-          $('.default', $thisButton).hide();
-
-          // Display a location.
-          var locationString = Drupal.t('Browser location: @lat,@lng', {'@lat': latDefault, '@lng': lngDefault});
-          $('.location', $thisButton).html(locationString);
-
-          // Disable the button.
-          $thisButton.addClass('disabled');
-
-          // Show the clear icon.
-          $('.clear', $thisButton).show();
-        }
-
-      });
-
-    }
-  };
-
-  $('.geolocation-html5-button .clear').on('click', function(event) {
-    // The parent element.
-    var $thisButton = $(this).parent();
-
-    // Prevent form submission.
-    event.stopPropagation()
-
-    // Clear the values of hidden form inputs.
-    $thisButton.siblings(".geolocation-hidden-lat").val('');
-    $thisButton.siblings(".geolocation-hidden-lng").val('');
-
-    // Show the default text.
-    $('.default', $thisButton).show();
-
-    // Clear the location message.
-    $('.location', $thisButton).html('');
-
-    // Hide the clear icon.
-    $('.clear', $thisButton).hide();
-
-    // Enable the button.
-    $thisButton.removeClass('disabled');
-
-  });
-
-  $('.geolocation-html5-button').on('click', function(event) {
-    // The parent element.
-    var $thisButton = $(this);
-
-    if ($thisButton.hasClass('disabled')) {
-      return;
-    }
-
-    // If the browser supports W3C Geolocation API.
-    if (navigator.geolocation) {
-
-      // Get the geolocation from the browser.
-      navigator.geolocation.getCurrentPosition(
-
-        // Success handler for getCurrentPosition()
-        function (position) {
-          var lat = position.coords.latitude;
-          var lng = position.coords.longitude;
-          var accuracy = position.coords.accuracy / 1000;
-
-          // Set the values of hidden form inputs.
-          $thisButton.siblings(".geolocation-hidden-lat").val(lat);
-          $thisButton.siblings(".geolocation-hidden-lng").val(lng);
-
-          // Hide the default text.
-          $('.default', $thisButton).hide();
-
-          // Display a success message.
-          var locationString = Drupal.t('Browser location: @lat,@lng Accuracy: @accuracy m', {'@lat': lat, '@lng': lng, '@accuracy': accuracy});
-          $('.location', $thisButton).html(locationString);
-
-          // Disable the button.
-          $thisButton.addClass('disabled');
-
-          // Show the clear icon.
-          $('.clear', $thisButton).show();
-        },
-
-        // Error handler for getCurrentPosition()
-        function(error) {
-
-          // Alert with error message.
-          switch(error.code) {
-            case error.PERMISSION_DENIED:
-              alert(Drupal.t('No location data found. Reason: PERMISSION_DENIED.'));
-              break;
-            case error.POSITION_UNAVAILABLE:
-              alert(Drupal.t('No location data found. Reason: POSITION_UNAVAILABLE.'));
-              break;
-            case error.TIMEOUT:
-              alert(Drupal.t('No location data found. Reason: TIMEOUT.'));
-              break;
-            default:
-              alert(Drupal.t('No location data found. Reason: Unknown error.'));
-              break;
-          }
-        },
-
-        // Options for getCurrentPosition()
-        {
-          enableHighAccuracy: true,
-          timeout: 5000,
-          maximumAge: 6000
-        }
-      );
-
-    } else {
-      alert(Drupal.t('No location data found. Your browser does not support the W3C Geolocation API.'));
-    }
-  });
-
-})(jQuery, Drupal, navigator);
diff --git a/js/geolocation-widget-googlegeocoder.js b/js/geolocation-widget-googlegeocoder.js
new file mode 100644
index 0000000..48c1e3d
--- /dev/null
+++ b/js/geolocation-widget-googlegeocoder.js
@@ -0,0 +1,83 @@
+/**
+ * @file
+ *   Javascript for the Google geocoder widget.
+ */
+
+(function ($, Drupal, drupalSettings) {
+  "use strict";
+
+  // Ensure and add shortcut to the geolocation object.
+  var geolocation = Drupal.geolocation = Drupal.geolocation || {};
+
+  Drupal.behaviors.geolocationGooglemaps = {
+    attach: function (context, settings) {
+      // Ensure itterables.
+      settings.geolocation = settings.geolocation || {widget_maps: []};
+      // Make sure the lazy loader is available.
+      if (typeof geolocation.load_google === 'function') {
+        // First load the library from google.
+        geolocation.load_google(function(){
+          // This won't fire until window load.
+          initialize(settings.geolocation.widget_maps);
+        });
+      }
+    }
+  };
+
+  /**
+   * Adds the click listeners to the map.
+   * @param map
+   */
+  geolocation.add_click_listener = function(map) {
+    // Used for a single click timeout.
+    var singleClick;
+    // Add the click listener.
+    google.maps.event.addListener(map.google_map, 'click', function(e) {
+      // Create 500ms timeout to wait for double click.
+      singleClick = setTimeout(function() {
+        geolocation.codeLatLng(e.latLng, map, 'marker');
+        geolocation.setMapMarker(e.latLng, map);
+      }, 500);
+    });
+    // Add a doubleclick listener.
+    google.maps.event.addListener(map.google_map, 'dblclick', function(e) {
+      clearTimeout(singleClick);
+    });
+  };
+
+  /**
+   * Runs after the google maps api is available
+   *
+   * @param maps
+   */
+  function initialize(maps) {
+    // Process drupalSettings for every Google map present on the current page.
+    $.each(maps, function(widget_id, map) {
+
+      // Get the container object.
+      map.container = document.getElementById(map.id);
+
+      if ($(map.container).length >= 1
+        && !$(map.container).hasClass('geolocation-processed')
+        && typeof google !== 'undefined'
+        && typeof google.maps !== 'undefined'
+      ) {
+        // Add any missing settings.
+        map.settings = $.extend(geolocation.default_settings(), map.settings);
+
+        // Add the map by ID with settings.
+        geolocation.add_map(map);
+
+        // Add the geocoder to the map.
+        geolocation.add_geocoder(map);
+
+        // Add the click responders ffor setting the value.
+        geolocation.add_click_listener(map);
+
+        // Set the already processed flag.
+        $(map.container).addClass('geolocation-processed');
+      }
+    });
+  }
+
+})(jQuery, Drupal, drupalSettings);
diff --git a/js/geolocation-widget-html5.js b/js/geolocation-widget-html5.js
new file mode 100644
index 0000000..be0d722
--- /dev/null
+++ b/js/geolocation-widget-html5.js
@@ -0,0 +1,157 @@
+/**
+ * @file
+ *   Javascript for the Geolocation HTML5 widget.
+ */
+
+(function ($, Drupal, navigator) {
+  "use strict";
+
+
+  Drupal.behaviors.geolocationHTML5 = {
+    attach: function(context, settings) {
+      $('.geolocation-html5-button:not(.disabled)').each( function(index) {
+        // The parent element.
+        var $thisButton = $(this);
+
+        // Set the values of hidden form inputs.
+        var latDefault = $thisButton.siblings(".geolocation-hidden-lat").val();
+        var lngDefault = $thisButton.siblings(".geolocation-hidden-lng").val();
+
+        if (latDefault.length > 1 && lngDefault.length > 1) {
+          // Hide the default text.
+          $('.default', $thisButton).hide();
+
+          // Display a location.
+          var locationString = Drupal.t('Browser location: @lat,@lng', {'@lat': latDefault, '@lng': lngDefault});
+          $('.location', $thisButton).html(locationString);
+
+          // Disable the button.
+          $thisButton.addClass('disabled');
+
+          // Show the clear icon.
+          $('.clear', $thisButton).show();
+        }
+
+      });
+
+    }
+  };
+
+  $('.geolocation-html5-button .clear').on('click', function(event) {
+    // The parent element.
+    var $thisButton = $(this).parent();
+
+    // Prevent form submission.
+    event.stopPropagation()
+
+    // Clear the values of hidden form inputs.
+    $thisButton.siblings(".geolocation-hidden-lat").val('');
+    $thisButton.siblings(".geolocation-hidden-lng").val('');
+
+    // Show the default text.
+    $('.default', $thisButton).show();
+
+    // Clear the location message.
+    $('.location', $thisButton).html('');
+
+    // Hide the clear icon.
+    $('.clear', $thisButton).hide();
+
+    // Enable the button.
+    $thisButton.removeClass('disabled');
+
+  });
+
+  $('.geolocation-html5-button').on('click', function(event) {
+    // The parent element.
+    var $thisButton = $(this);
+
+    if ($thisButton.hasClass('disabled')) {
+      return;
+    }
+
+    // If the browser supports W3C Geolocation API.
+    if (navigator.geolocation) {
+
+      // Get the geolocation from the browser.
+      navigator.geolocation.getCurrentPosition(
+
+        // Success handler for getCurrentPosition()
+        function (position) {
+          var lat = position.coords.latitude;
+          var lng = position.coords.longitude;
+          var accuracy = position.coords.accuracy / 1000;
+
+          // Set the values of hidden form inputs.
+          $thisButton.siblings(".geolocation-hidden-lat").val(lat);
+          $thisButton.siblings(".geolocation-hidden-lng").val(lng);
+
+          // Hide the default text.
+          $('.default', $thisButton).hide();
+
+          // Display a success message.
+          var locationString = Drupal.t('Browser location: @lat,@lng Accuracy: @accuracy m', {'@lat': lat, '@lng': lng, '@accuracy': accuracy});
+          $('.location', $thisButton).html(locationString);
+
+          // Disable the button.
+          $thisButton.addClass('disabled');
+
+          // Show the clear icon.
+          $('.clear', $thisButton).show();
+        },
+
+        // Error handler for getCurrentPosition()
+        function(error) {
+
+          // Alert with error message.
+          switch(error.code) {
+            case error.PERMISSION_DENIED:
+              alert(Drupal.t('No location data found. Reason: PERMISSION_DENIED.'));
+              break;
+            case error.POSITION_UNAVAILABLE:
+              alert(Drupal.t('No location data found. Reason: POSITION_UNAVAILABLE.'));
+              break;
+            case error.TIMEOUT:
+              alert(Drupal.t('No location data found. Reason: TIMEOUT.'));
+              break;
+            default:
+              alert(Drupal.t('No location data found. Reason: Unknown error.'));
+              break;
+          }
+        },
+
+        // Options for getCurrentPosition()
+        {
+          enableHighAccuracy: true,
+          timeout: 5000,
+          maximumAge: 6000
+        }
+      );
+
+    } else {
+      alert(Drupal.t('No location data found. Your browser does not support the W3C Geolocation API.'));
+    }
+  });
+
+  /**
+   * Runs after the google maps api is available
+   *
+   * @param settings
+   */
+  function initialize(settings) {
+
+    // Process drupalSettings for every Google map present on the current page.
+    $.each(settings.geolocation.widget_maps, function(widget_id, map) {
+
+      // Add any missing settings.
+      map.settings = $.extend(geolocation.default_settings(), map.settings);
+
+      // Add the map by ID with settings.
+      geolocation.add_map(map);
+
+      // Add the click responders ffor setting the value.
+      geolocation.add_click_listener(map);
+    });
+  }
+
+})(jQuery, Drupal, navigator);
diff --git a/js/geolocation.js b/js/geolocation.js
new file mode 100644
index 0000000..888b421
--- /dev/null
+++ b/js/geolocation.js
@@ -0,0 +1,229 @@
+/**
+ * @file
+ *   Javascript for the geocoder module.
+ */
+(function ($, _, Drupal, settings) {
+  // Ensure the geolocation object without overwriting it.
+  var geolocation = Drupal.geolocation = Drupal.geolocation || {};
+
+  /**
+   * Gets the default settings for the google map.
+   *
+   * @returns {{scrollwheel: boolean, panControl: boolean, mapTypeControl: boolean, scaleControl: boolean, streetViewControl: boolean, overviewMapControl: boolean, zoomControl: boolean, zoomControlOptions: {style: *, position: *}, mapTypeId: *, zoom: number}}
+   */
+  geolocation.default_settings = function() {
+    return {
+      scrollwheel: false,
+      panControl: false,
+      mapTypeControl: true,
+      scaleControl: false,
+      streetViewControl: false,
+      overviewMapControl: false,
+      zoomControl: true,
+      zoomControlOptions: {
+        style: google.maps.ZoomControlStyle.LARGE,
+        position: google.maps.ControlPosition.LEFT_TOP
+      },
+      mapTypeId: google.maps.MapTypeId.ROADMAP,
+      zoom: 2
+    };
+  };
+
+  /**
+   * Provides the callback that is called when maps loads.
+   */
+  geolocation.google_callback = function() {
+    // Ensure callbacks array;
+    geolocation.google_load_callbacks = geolocation.google_load_callbacks || [];
+
+    // Wait until the window load event to try to use the maps library.
+    $(document).ready(function(e) {
+      _.invoke(settings.geolocation.google_load_callbacks, "callback");
+      geolocation.google_load_callbacks = [];
+    });
+  };
+
+  /**
+   * Adds a callback that will be called once the maps library is loaded.
+   *
+   * @param callback
+   */
+  geolocation.add_callback = function(callback) {
+    settings.geolocation.google_load_callbacks = geolocation.google_load_callbacks || [];
+    settings.geolocation.google_load_callbacks.push({callback: callback});
+  };
+
+  /**
+   * Load google maps and set a callback to run when it's ready.
+   *
+   * @param callback
+   */
+  geolocation.load_google = function(callback) {
+    // Add the callback.
+    geolocation.add_callback(callback);
+    // Check for google maps.
+    if (typeof google == 'undefined' || typeof google.maps == 'undefined') {
+      // google maps isn't loaded so lazy load google maps.
+      $.getScript("//maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&callback=Drupal.geolocation.google_callback");
+    } else {
+      // Google maps loaded. Run callback.
+      geolocation.google_callback();
+    }
+  };
+
+  /**
+   * Load google maps and set a callback to run when it's ready.
+   *
+   * @param map
+   */
+  geolocation.add_map = function(map) {
+    // Set the container size.
+    $(map.container).css({
+      height: map.settings.height,
+      width: map.settings.width
+    });
+
+    // Get the center point.
+    var center = new google.maps.LatLng(map.lat, map.lng);
+
+    // Create the map object and assign it to the map.
+    map.google_map = new google.maps.Map(map.container, {
+      zoom: parseInt(map.settings.zoom),
+      center: center,
+      mapTypeId: google.maps.MapTypeId[map.settings.type]
+    });
+
+    // Set the map marker.
+    if (map.lat != '' && map.lng != '') {
+      geolocation.setMapMarker(center, map);
+    }
+  };
+
+  /**
+   * Load google maps and set a callback to run when it's ready.
+   *
+   * @param map
+   */
+  geolocation.add_geocoder = function(map) {
+    /**
+     * Callback for geocoder controls click submit.
+     *
+     * @param e
+     *   The event from input keypress or the click of the submit button.
+     */
+    var handleControlEvent = function(e) {
+      if (typeof e.keyCode === 'undefined' || e.keyCode === 13) {
+        // We don't any forms submitting.
+        e.preventDefault();
+        // Get the address from the input value.
+        var address = $(e.target).parent().children('input.input').val();
+        // Make sure there are at least 2 characters for geocoding.
+        if (address.length > 1) {
+          // Run the geocode function with google maps.
+          map.geocoder.geocode({'address': address}, function (results, status) {
+            if (status == google.maps.GeocoderStatus.OK) {
+              // Set the map viewport.
+              map.google_map.fitBounds(results[0].geometry.viewport);
+              // Set the values for the field.
+              geolocation.codeLatLng(results[0].geometry.location, map);
+              // Set the map marker.
+              geolocation.setMapMarker(results[0].geometry.location, map);
+            }
+            else {
+              // Alert of the error geocoding.
+              alert(Drupal.t('Geocode was not successful for the following reason: ') + status);
+            }
+          });
+        }
+      }
+    };
+
+    map.geocoder = new google.maps.Geocoder();
+    map.controls = $('<div class="geocode-controlls-wrapper" />')
+      .append($('<input type="text" class="input" placeholder="Enter a location" />'))
+      // Create submit button
+      .append($('<button class="submit" />'))
+      // Create clear button
+      .append($('<button class="clear" />'))
+      // Create clear button
+      .append($('<div class="geolocation-map-indicator" />'))
+      // Use the DOM element.
+      .get(0);
+
+    // Add the default indicator if the values aren't blank.
+    if (map.lat != '' && map.lng != '') {
+      $(map.controls).children('.geolocation-map-indicator')
+        .addClass('has-location')
+        .text(map.lat+', '+map.lng);
+    }
+
+    map.controls.index = 1;
+
+    map.google_map.controls[google.maps.ControlPosition.TOP_LEFT].push(map.controls);
+
+    // Add the listened for the search click event.
+    google.maps.event.addDomListener($(map.controls).children('button.submit')[0], 'click', handleControlEvent);
+    // Add the listened for the search click event.
+    google.maps.event.addDomListener($(map.controls).children('input.input')[0], 'keyup', handleControlEvent);
+    // Add the event listener for the remove button.
+    google.maps.event.addDomListener($(map.controls).children('button.clear')[0], 'click', function(e) {
+      // Stop all that bubbling and form submitting.
+      e.preventDefault();
+      // Remove the coordinates.
+      $(map.controls).children('.geolocation-map-indicator').text('').removeClass('has-location');
+      // Clear the map point.
+      map.marker.setMap();
+      // Clear the input text.
+      $(map.controls).children('input.input').val('');
+      // Remove the form values.
+      // Update the lat and lng input fields
+      $('.geolocation-hidden-lat.for-'+map.id).attr('value', '');
+      $('.geolocation-hidden-lng.for-'+map.id).attr('value', '');
+    });
+  };
+
+  /**
+   * Set the latitude and longitude values to the input fields
+   * And optionally update the address field
+   *
+   * @param latLng
+   *   a location (latLng) object from google maps api
+   * @param map
+   *   The settings object that contains all of the necessary metadata for this map.
+   * @param op
+   *   the op that was performed
+   */
+  geolocation.codeLatLng = function(latLng, map) {
+    // Update the lat and lng input fields
+    $('.geolocation-hidden-lat.for-'+map.id).attr('value', latLng.lat());
+    $('.geolocation-hidden-lng.for-'+map.id).attr('value', latLng.lng());
+  };
+
+  /**
+   * Set/Update a marker on a map
+   *
+   * @param latLng
+   *   a location (latLng) object from google maps api
+   * @param map
+   *   The settings object that contains all of the necessary metadata for this map.
+   */
+  geolocation.setMapMarker = function(latLng, map) {
+    // make sure the marker exists.
+    if (typeof map.marker !== 'undefined') {
+      map.marker.setPosition(latLng);
+      map.marker.setMap(map.google_map);
+    } else {
+      // Add the marker to the map.
+      map.marker = new google.maps.Marker({
+        position: latLng,
+        map: map.google_map
+      });
+    }
+
+    // Add a visual indicator.
+    $(map.controls).children('.geolocation-map-indicator')
+      .text(latLng.lat()+', '+latLng.lng())
+      .addClass('has-location');
+  };
+
+})(jQuery, _, Drupal, drupalSettings);
diff --git a/src/Plugin/Field/FieldFormatter/GeolocationGoogleMapFormatter.php b/src/Plugin/Field/FieldFormatter/GeolocationGoogleMapFormatter.php
new file mode 100644
index 0000000..de9d956
--- /dev/null
+++ b/src/Plugin/Field/FieldFormatter/GeolocationGoogleMapFormatter.php
@@ -0,0 +1,133 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\geolocation\Plugin\Field\FieldFormatter\GeolocationGoogleMapFormatter.
+ */
+
+namespace Drupal\geolocation\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\FormatterBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Plugin implementation of the 'geolocation_latlng' formatter.
+ *
+ * @FieldFormatter(
+ *   id = "geolocation_map",
+ *   module = "geolocation",
+ *   label = @Translation("Geolocation Google Map"),
+ *   field_types = {
+ *     "geolocation"
+ *   }
+ * )
+ */
+class GeolocationGoogleMapFormatter extends FormatterBase {
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    return array(
+      'type' => 'ROADMAP',
+      'zoom' => 10,
+      'height' => '400px',
+      'width' => '100%',
+    ) + parent::defaultSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $settings = $this->getSettings();
+    $elements['type'] = array(
+      '#type' => 'select',
+      '#title' => t('Default map type'),
+      '#options' => $this->getMapTypes(),
+      '#default_value' =>  $settings['type'],
+    );
+    $elements['zoom'] = array(
+      '#type' => 'select',
+      '#title' => t('Zoom level'),
+      '#options' => range(0, 18),
+      '#description' => t('The initial resolution at which to display the map, where zoom 0 corresponds to a map of the Earth fully zoomed out, and higher zoom levels zoom in at a higher resolution.'),
+      '#default_value' => $settings['zoom'],
+    );
+    $elements['height'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Height'),
+      '#description' => t('Enter the dimensions and the measurement units. E.g. 200px or 100%.'),
+      '#size' => 4,
+      '#default_value' => $settings['height'],
+    );
+    $elements['width'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Width'),
+      '#description' => t('Enter the dimensions and the measurement units. E.g. 200px or 100%.'),
+      '#size' => 4,
+      '#default_value' => $settings['width'],
+    );
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $settings = $this->getSettings();
+    $types = $this->getMapTypes();
+    $summary = array();
+    $summary[] = t('Type: @type', array('@type' => $types[$settings['type']]));
+    $summary[] = t('Zoom level: @zoom', array('@zoom' => $settings['zoom']));
+    $summary[] = t('Height: @height', array('@height' => $settings['height']));
+    $summary[] = t('Width: @width', array('@width' => $settings['width']));
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items) {
+    // Add formatter settings to the drupalSettings array.
+    $field_settings = $this->getSettings();
+    $elements =  [];
+    foreach ($items as $item) {
+      $uniqueue_id = uniqid("map-canvas-");
+
+      $elements[] = [
+        '#type' => 'markup',
+        '#markup' => '<div id="' . $uniqueue_id . '" class="geolocation-google-map"></div>',
+        '#attached' => [
+          'library' => ['geolocation/geolocation.maps'],
+          'drupalSettings' => [
+            'geolocation' => [
+              'maps' => [
+                $uniqueue_id => [
+                  'id' => "{$uniqueue_id}",
+                  'lat' => (float)$item->lat,
+                  'lng' => (float)$item->lng,
+                  'settings' => $field_settings,
+                ],
+              ],
+            ],
+          ],
+        ],
+      ];
+    }
+    return $elements;
+  }
+
+  /**
+   * An array of all available map types.
+   *
+   * @return array
+   */
+  private function getMapTypes() {
+    return array(
+      'ROADMAP' => t('Road map view'),
+      'SATELLITE' => t('Google Earth satellite images'),
+      'HYBRID' => t('A mixture of normal and satellite views'),
+      'TERRAIN' => t('A physical map based on terrain information'),
+    );
+  }
+}
diff --git a/src/Plugin/Field/FieldWidget/GeolocationGooglegeocoderWidget.php b/src/Plugin/Field/FieldWidget/GeolocationGooglegeocoderWidget.php
index fb4b41e..913f8d0 100644
--- a/src/Plugin/Field/FieldWidget/GeolocationGooglegeocoderWidget.php
+++ b/src/Plugin/Field/FieldWidget/GeolocationGooglegeocoderWidget.php
@@ -27,11 +27,27 @@ class GeolocationGooglegeocoderWidget extends WidgetBase {
    * {@inheritdoc}
    */
   public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
+    // Get this field name and parent.
+    $field_name = $this->fieldDefinition->getName();
+    $parents = $form['#parents'];
+    // Get the field state.
+    $field_state = static::getWidgetState($parents, $field_name, $form_state);
 
     // Create a unique canvas id for each map of each geolocation field instance.
-    $field_name = $this->fieldDefinition->getName();
-    $canvas_id = 'map_canvas_' . $field_name . '_' . $delta;
+    $field_id = preg_replace('/[^a-zA-Z0-9\-]/', '-', $this->fieldDefinition->getName());
+    $canvas_id = !empty($field_state['canvas_ids'][$delta])
+      ? $field_state['canvas_ids'][$delta]
+      : uniqid("map-canvas-{$field_id}-");
+
+    // Add the canvas id for this field.
+    $field_state['canvas_ids'] = isset($field_state['canvas_ids'])
+      ?  $field_state['canvas_ids'] + [$delta => $canvas_id]
+      : [$delta => $canvas_id];
 
+    // Save the field state for this field.
+    static::setWidgetState($parents, $field_name, $form_state, $field_state);
+
+    // Get the geolocation value for this element.
     $lat = $items[$delta]->lat;
     $lng = $items[$delta]->lng;
 
@@ -39,52 +55,46 @@ class GeolocationGooglegeocoderWidget extends WidgetBase {
     $lat_default_value = isset($lat) ? $lat : NULL;
     $lng_default_value = isset($lng) ? $lng : NULL;
 
-    // The map container.
-    $element['map_canvas'] = [
-      '#type' => 'html_tag',
-      '#tag' => 'div',
-      '#attributes' => [
-        'id' => $canvas_id,
-        'class' => ['geolocation-map-canvas'],
-      ],
-    ];
-
     // Hidden lat,lng input fields.
     $element['lat'] = [
       '#type' => 'hidden',
       '#default_value' => $lat_default_value,
-      '#attributes' => ['class' => ['geolocation-hidden-lat']],
+      '#attributes' => ['class' => ['geolocation-hidden-lat', "for-{$canvas_id}"]],
     ];
     $element['lng'] = [
       '#type' => 'hidden',
       '#default_value' => $lng_default_value,
-      '#attributes' => ['class' => ['geolocation-hidden-lng']],
-    ];
-
-    // Make default values available as javascript settings. Example: To access
-    // the default lat value via javascript use: drupalSettings.mapDefaults.lat
-    $data = [
-      'defaults' => [
-        "$canvas_id" => [
-          'lat' => $lat_default_value,
-          'lng' => $lng_default_value,
-        ],
-      ],
+      '#attributes' => ['class' => ['geolocation-hidden-lng', "for-{$canvas_id}"]],
     ];
 
-    // Attach widget library and js settings
-    $element['#attached'] = [
-      'library' => [
-        'geolocation/geolocation.widgets.googlegeocoder',
+    // Add the map container.
+    $element['map_canvas'] = [
+      '#type' => 'html_tag',
+      '#tag' => 'div',
+      '#attributes' => [
+        'id' => $canvas_id,
+        'class' => ['geolocation-map-canvas'],
       ],
-      'drupalSettings' => [
-        'geolocation' => $data
+      '#attached' => [
+        'library' => ['geolocation/geolocation.widgets.googlegeocoder'],
+        'drupalSettings' => [
+          'geolocation' => [
+            'widget_maps' => [
+              $canvas_id => [
+                'id' => $canvas_id,
+                'lat' => (float)$lat_default_value,
+                'lng' => (float)$lng_default_value,
+                'settings' => [],
+              ],
+            ],
+          ],
+        ],
       ],
     ];
 
     // Wrap the whole form in a container.
     $element += [
-      '#type' => 'item',
+      '#type' => 'container',
       '#title' => $element['#title'],
     ];
 
