diff --git a/package/gluon-config-mode-theme/files/lib/gluon/config-mode/www/static/gluon.css b/package/gluon-config-mode-theme/files/lib/gluon/config-mode/www/static/gluon.css
index c75fffcd76c4435ff61236faf7ee97520125696c..bbb82a8ab492117f4cafbee34d256af3a0076abe 100644
--- a/package/gluon-config-mode-theme/files/lib/gluon/config-mode/www/static/gluon.css
+++ b/package/gluon-config-mode-theme/files/lib/gluon/config-mode/www/static/gluon.css
@@ -1 +1 @@
-.lang_he{direction:RTL;unicode-bidi:embed}.hidden{display:none}html{min-height:100%;height:auto;position:relative}body,input,select,option{font-family:'Open Sans', Arial, sans-serif;font-size:12pt}body{color:#4d4e53;line-height:1.5em;margin:0;display:flex;flex-direction:column;min-height:100vh;background-color:#f3f3f3}a img{border:none;text-decoration:none}.tabmenu1{text-align:center}ul.tabmenu{list-style:none;padding:0;margin:2em 0;display:inline-flex}ul.tabmenu li{white-space:nowrap;margin:0 0.5em;padding:0;text-align:center}ul.tabmenu li a{display:block;text-decoration:none;padding:1em;margin:0;color:#333;border-radius:2em}ul.tabmenu li a:hover{background:#ffe9b3}ul.tabmenu li.active a{font-weight:bold;background:white;color:#333}abbr,acronym{font-style:normal;font-variant:normal}abbr[title],acronym[title]{border-bottom:1px dotted;cursor:help}a:link abbr[title],a:visited abbr[title],a:link acronym[title],a:visited acronym[title]{cursor:pointer}code{font-family:monospace;white-space:pre}#maincontent ul{margin-left:2em}.clear{clear:both}.error{color:#ff0000;background-color:white}#menubar{display:flex;background:#dc0067;color:#ffffff}#menubar a:link.topcat,#menubar a:visited.topcat{position:relative;display:block;padding:0.5em;text-decoration:none;font-size:80%;font-weight:normal;color:white}#menubar a:link.topcat:hover,#menubar a:link.topcat:focus,#menubar a:visited.topcat:hover,#menubar a:visited.topcat:focus{background:#ffb400;color:black}#menubar a:link.topcat.active,#menubar a:visited.topcat.active{background:#ffb400;color:black;font-weight:bold}#menubar div.hostinfo{position:relative;margin:0;padding:0.5em;flex:1;font-weight:bold;font-size:80%}#menubar div.hostinfo a:link,#menubar div.hostinfo a:visited{text-decoration:none;font-weight:bold;color:white}#menubar div.hostinfo a:link:hover,#menubar div.hostinfo a:link:focus,#menubar div.hostinfo a:visited:hover,#menubar div.hostinfo a:visited:focus{text-decoration:underline}#topmenu{list-style:none;margin:0;padding:0}#topmenu li{display:inline-block}#maincontent{padding:0 1em 2em;max-width:60em;min-width:40em;margin:1em auto}#maincontent p{margin-bottom:1em}.gluon-section{margin:0;padding:0;border:none;margin-bottom:1.3em}.gluon-section:last-child{margin-bottom:0.7em}.gluon-section legend{font-size:1.4em;font-weight:bold;position:relative;padding:0;margin-bottom:0.5em}.gluon-section h2{margin:0em 0 0.5em -0.5em !important}.gluon-section h3{text-decoration:none !important;font-weight:bold !important;color:#555555 !important;margin:0.25em !important;font-size:100% !important}.gluon-section-descr{margin-bottom:2em}input:placeholder{color:#aaaaaa}input:-webkit-input-placeholder{color:#aaaaaa}input:-moz-placeholder{color:#aaaaaa}input:-ms-input-placeholder{color:#aaaaaa}input[type=checkbox]{display:none}input[type=checkbox]+label{display:inline-block;position:relative;width:1em;height:1em;margin:0}input[type=checkbox]:checked+label:after{content:'✔';color:#dc0067;vertical-align:middle;position:absolute;top:50%;left:0;margin-top:-0.5em;width:100%;text-align:center;font-size:1.7em}input[type=radio]{display:none}input[type=radio]+label{display:inline-block;position:relative;width:0.8em;height:0.8em;padding:0.5em;margin:0.2em 0.2em 0.2em 0.1em;border:none;background:#ffe199;vertical-align:middle;border-radius:50%}input[type=radio]:checked+label:after{content:'•';color:#dc0067;vertical-align:middle;position:absolute;top:50%;left:0;margin-top:-0.4em;width:100%;text-align:center;font-size:2em}input[type=submit],input[type=reset],input[type=image],input[type=button]{cursor:pointer}select,input,textarea,input[type=checkbox]+label{color:#003247;border:none;background:#ffe199;border-radius:3pt;padding:0.5em;margin-top:1px;margin-bottom:2px;box-sizing:content-box;outline:0}option{color:#003247;background:#ffe199}input[type=image]{border:none}select,input[type=text],input[type=password]{min-width:20em}input.gluon-button{display:inline-block;zoom:1;line-height:normal;white-space:nowrap;vertical-align:baseline;text-align:center;cursor:pointer;user-select:none;font-size:100%;padding:0.5em 1em;color:rgba(0,0,0,0.8);border:none transparent;background-color:#E6E6E6;text-decoration:none;border-radius:2px;transition:0.1s linear box-shadow;margin-left:0.5em;background-repeat:no-repeat}input.gluon-button::-moz-focus-inner{padding:0;border:0}input.gluon-button:active{box-shadow:0 0 0 1px rgba(0,0,0,0.15) inset,0 0 6px rgba(0,0,0,0.2) inset}input.gluon-button:focus{outline:0}input.gluon-button:hover,input.gluon-button:focus{background-image:linear-gradient(transparent, rgba(0,0,0,0.05) 40%, rgba(0,0,0,0.1))}input.gluon-button[disabled]{border:none;background-image:none;opacity:0.40;cursor:not-allowed;box-shadow:none}input.gluon-button-reset{background-color:#e30;color:#fff}input.gluon-button-submit{background-color:#009ee0;color:#fff}input.gluon-button-submit:active{background:grey}.gluon-input-invalid{background:#e30 !important;color:white}div.gluon-section-remove input{border-bottom:none}textarea{margin-left:-1px;margin-bottom:0.5em}.gluon-section .gluon-rowstyle-1 h3{background-color:#eeeeff;color:#555555}.gluon-rowstyle-2{color:#000000}div.gluon-value{display:flex;flex-direction:row;margin-bottom:0.5em}.gluon-section-node .gluon-value:last-child{margin-bottom:0}.gluon-value-title{flex:2;text-align:right;padding-top:0.39em;padding-right:1em;font-weight:bold}div.gluon-value-field{flex:3;position:relative}div.gluon-value-field input,div.gluon-value-field select,div.gluon-value-field input+label{position:relative}div.gluon-value-field-text{flex:3;padding-top:0.39em}div.gluon-value-field-long{flex:10;position:relative;margin-top:0.65em}div.gluon-value-field-long input,div.gluon-value-field-long select,div.gluon-value-field-long input+label{position:relative}div.gluon-value-field-long-after{flex:2}div.gluon-value-description{font-size:8pt}div.gluon-section-create{clear:left;white-space:nowrap;vertical-align:top}div.gluon-section-create .gluon-button{margin:0.25em}input.gluon-section-create-name{margin-right:-0.25em}div.gluon-form-descr{margin-bottom:1em}.gluon-form-descr:empty,.gluon-section-descr:empty{display:none}.gluon-form-descr,.gluon-section-descr,.gluon-page-actions{padding:1em;background:#ececec}.gluon-page-actions{text-align:right;display:flex;flex-flow:row-reverse}div.gluon-optionals{padding:0.25em;border-bottom:1px dotted #bbbbbb}div.gluon-section-remove{float:right}.gluon-section-node{clear:both;position:relative;border:none}.gluon-section-node-tabbed{border-top-left-radius:0}div.gluon-error{font-size:95%;font-weight:bold;color:#ff0000;background-color:#ffffff}.gluon-value-error input,.gluon-value-error select{background-color:#ffcccc}.gluon-section-error{color:red;background-color:white;font-size:95%;border:1px dotted red;margin:3px;padding:3px}.gluon-value-field var{color:#2222FF}.gluon-add:after,.gluon-remove:after{cursor:pointer;display:inline-block;text-align:center;vertical-align:middle;font-size:180%;width:1.2em;height:1em}.gluon-add{color:#008000;position:relative;left:21em}input+.gluon-add{left:0;top:0.04em}.gluon-add:first-child{top:0.53em;left:-0.08em}.gluon-add:after{content:'+'}.gluon-remove{color:#800000;position:relative;top:-0.03em}.gluon-remove:after{content:'–'}.left{text-align:left !important}.right{text-align:right !important}.inline{display:inline}.error500{border:1px dotted #ff0000;background-color:#ffffff;color:#000000;padding:0.5em}.errorbox{border:1px solid #FF0000;background-color:#FFCCCC;padding:5px;margin-bottom:5px}.errorbox a{color:#000000 !important}.the-key{text-align:left;font-size:1.4em;background:#ffe9b3;border:3pt dashed #dc0067;margin-bottom:0.5em;padding:0.5em}
+.lang_he{direction:RTL;unicode-bidi:embed}.hidden{display:none}html{min-height:100%;height:auto;position:relative}body,input,select,option{font-family:'Open Sans', Arial, sans-serif;font-size:12pt}body{color:#4d4e53;line-height:1.5em;margin:0;display:flex;flex-direction:column;min-height:100vh;background-color:#f3f3f3}a img{border:none;text-decoration:none}.tabmenu1{text-align:center}ul.tabmenu{list-style:none;padding:0;margin:2em 0;display:inline-flex}ul.tabmenu li{white-space:nowrap;margin:0 0.5em;padding:0;text-align:center}ul.tabmenu li a{display:block;text-decoration:none;padding:1em;margin:0;color:#333;border-radius:2em}ul.tabmenu li a:hover{background:#ffe9b3}ul.tabmenu li.active a{font-weight:bold;background:white;color:#333}abbr,acronym{font-style:normal;font-variant:normal}abbr[title],acronym[title]{border-bottom:1px dotted;cursor:help}a:link abbr[title],a:visited abbr[title],a:link acronym[title],a:visited acronym[title]{cursor:pointer}code{font-family:monospace;white-space:pre}#maincontent ul{margin-left:2em}.clear{clear:both}.error{color:#ff0000;background-color:white}#menubar{display:flex;background:#dc0067;color:#ffffff}#menubar a:link.topcat,#menubar a:visited.topcat{position:relative;display:block;padding:0.5em;text-decoration:none;font-size:80%;font-weight:normal;color:white}#menubar a:link.topcat:hover,#menubar a:link.topcat:focus,#menubar a:visited.topcat:hover,#menubar a:visited.topcat:focus{background:#ffb400;color:black}#menubar a:link.topcat.active,#menubar a:visited.topcat.active{background:#ffb400;color:black;font-weight:bold}#menubar div.hostinfo{position:relative;margin:0;padding:0.5em;flex:1;font-weight:bold;font-size:80%}#menubar div.hostinfo a:link,#menubar div.hostinfo a:visited{text-decoration:none;font-weight:bold;color:white}#menubar div.hostinfo a:link:hover,#menubar div.hostinfo a:link:focus,#menubar div.hostinfo a:visited:hover,#menubar div.hostinfo a:visited:focus{text-decoration:underline}#topmenu{list-style:none;margin:0;padding:0}#topmenu li{display:inline-block}#maincontent{padding:0 1em 2em;max-width:60em;min-width:40em;margin:1em auto}#maincontent p{margin-bottom:1em}.gluon-section{margin:0;padding:0;border:none;margin-bottom:1.3em}.gluon-section:last-child{margin-bottom:0.7em}.gluon-section legend{font-size:1.4em;font-weight:bold;position:relative;padding:0;margin-bottom:0.5em}.gluon-section h2{margin:0em 0 0.5em -0.5em !important}.gluon-section h3{text-decoration:none !important;font-weight:bold !important;color:#555555 !important;margin:0.25em !important;font-size:100% !important}.gluon-section-descr{margin-bottom:2em}.gluon-osm-map{width:100%;height:40em;margin-bottom:1em}input:placeholder{color:#aaaaaa}input:-webkit-input-placeholder{color:#aaaaaa}input:-moz-placeholder{color:#aaaaaa}input:-ms-input-placeholder{color:#aaaaaa}input[type=checkbox]{display:none}input[type=checkbox]+label{display:inline-block;position:relative;width:1em;height:1em;margin:0}input[type=checkbox]:checked+label:after{content:'✔';color:#dc0067;vertical-align:middle;position:absolute;top:50%;left:0;margin-top:-0.5em;width:100%;text-align:center;font-size:1.7em}input[type=radio]{display:none}input[type=radio]+label{display:inline-block;position:relative;width:0.8em;height:0.8em;padding:0.5em;margin:0.2em 0.2em 0.2em 0.1em;border:none;background:#ffe199;vertical-align:middle;border-radius:50%}input[type=radio]:checked+label:after{content:'•';color:#dc0067;vertical-align:middle;position:absolute;top:50%;left:0;margin-top:-0.4em;width:100%;text-align:center;font-size:2em}input[type=submit],input[type=reset],input[type=image],input[type=button]{cursor:pointer}select,input,textarea,input[type=checkbox]+label{color:#003247;border:none;background:#ffe199;border-radius:3pt;padding:0.5em;margin-top:1px;margin-bottom:2px;box-sizing:content-box;outline:0}option{color:#003247;background:#ffe199}input[type=image]{border:none}select,input[type=text],input[type=password]{min-width:20em}input.gluon-button{display:inline-block;zoom:1;line-height:normal;white-space:nowrap;vertical-align:baseline;text-align:center;cursor:pointer;user-select:none;font-size:100%;padding:0.5em 1em;color:rgba(0,0,0,0.8);border:none transparent;background-color:#E6E6E6;text-decoration:none;border-radius:2px;transition:0.1s linear box-shadow;margin-left:0.5em;background-repeat:no-repeat}input.gluon-button::-moz-focus-inner{padding:0;border:0}input.gluon-button:active{box-shadow:0 0 0 1px rgba(0,0,0,0.15) inset,0 0 6px rgba(0,0,0,0.2) inset}input.gluon-button:focus{outline:0}input.gluon-button:hover,input.gluon-button:focus{background-image:linear-gradient(transparent, rgba(0,0,0,0.05) 40%, rgba(0,0,0,0.1))}input.gluon-button[disabled]{border:none;background-image:none;opacity:0.40;cursor:not-allowed;box-shadow:none}input.gluon-button-reset{background-color:#e30;color:#fff}input.gluon-button-submit{background-color:#009ee0;color:#fff}input.gluon-button-submit:active{background:grey}.gluon-input-invalid{background:#e30 !important;color:white}div.gluon-section-remove input{border-bottom:none}textarea{margin-left:-1px;margin-bottom:0.5em}.gluon-section .gluon-rowstyle-1 h3{background-color:#eeeeff;color:#555555}.gluon-rowstyle-2{color:#000000}div.gluon-value{display:flex;flex-direction:row;margin-bottom:0.5em}.gluon-section-node .gluon-value:last-child{margin-bottom:0}.gluon-value-title{flex:2;text-align:right;padding-top:0.39em;padding-right:1em;font-weight:bold}div.gluon-value-field{flex:3;position:relative}div.gluon-value-field input,div.gluon-value-field select,div.gluon-value-field input+label{position:relative}div.gluon-value-field-text{flex:3;padding-top:0.39em}div.gluon-value-field-long{flex:10;position:relative;margin-top:0.65em}div.gluon-value-field-long input,div.gluon-value-field-long select,div.gluon-value-field-long input+label{position:relative}div.gluon-value-field-long-after{flex:2}div.gluon-value-description{font-size:8pt}div.gluon-section-create{clear:left;white-space:nowrap;vertical-align:top}div.gluon-section-create .gluon-button{margin:0.25em}input.gluon-section-create-name{margin-right:-0.25em}div.gluon-form-descr{margin-bottom:1em}.gluon-form-descr:empty,.gluon-section-descr:empty{display:none}.gluon-form-descr,.gluon-section-descr,.gluon-page-actions{padding:1em;background:#ececec}.gluon-page-actions{text-align:right;display:flex;flex-flow:row-reverse}div.gluon-optionals{padding:0.25em;border-bottom:1px dotted #bbbbbb}div.gluon-section-remove{float:right}.gluon-section-node{clear:both;position:relative;border:none}.gluon-section-node-tabbed{border-top-left-radius:0}div.gluon-error{font-size:95%;font-weight:bold;color:#ff0000;background-color:#ffffff}.gluon-value-error input,.gluon-value-error select{background-color:#ffcccc}.gluon-section-error{color:red;background-color:white;font-size:95%;border:1px dotted red;margin:3px;padding:3px}.gluon-value-field var{color:#2222FF}.gluon-add:after,.gluon-remove:after{cursor:pointer;display:inline-block;text-align:center;vertical-align:middle;font-size:180%;width:1.2em;height:1em}.gluon-add{color:#008000;position:relative;left:21em}input+.gluon-add{left:0;top:0.04em}.gluon-add:first-child{top:0.53em;left:-0.08em}.gluon-add:after{content:'+'}.gluon-remove{color:#800000;position:relative;top:-0.03em}.gluon-remove:after{content:'–'}.left{text-align:left !important}.right{text-align:right !important}.inline{display:inline}.error500{border:1px dotted #ff0000;background-color:#ffffff;color:#000000;padding:0.5em}.errorbox{border:1px solid #FF0000;background-color:#FFCCCC;padding:5px;margin-bottom:5px}.errorbox a{color:#000000 !important}.the-key{text-align:left;font-size:1.4em;background:#ffe9b3;border:3pt dashed #dc0067;margin-bottom:0.5em;padding:0.5em}
diff --git a/package/gluon-config-mode-theme/sass/gluon.scss b/package/gluon-config-mode-theme/sass/gluon.scss
index 7d48c3546332871486f609d23928326b5c426fd5..e534995f08a3536cd09c9c7f66b496b82c41b6a3 100644
--- a/package/gluon-config-mode-theme/sass/gluon.scss
+++ b/package/gluon-config-mode-theme/sass/gluon.scss
@@ -284,6 +284,12 @@ code {
   margin-bottom: 2em;
 }
 
+.gluon-osm-map {
+  width: 100%;
+  height: 40em;
+  margin-bottom: 1em;
+}
+
 input:placeholder {
   color: #aaaaaa;
 }
diff --git a/package/gluon-web-osm/files/lib/gluon/web/view/model/osm/map.html b/package/gluon-web-osm/files/lib/gluon/web/view/model/osm/map.html
new file mode 100644
index 0000000000000000000000000000000000000000..1a42c5104460270423f935c033560fc1389c967d
--- /dev/null
+++ b/package/gluon-web-osm/files/lib/gluon/web/view/model/osm/map.html
@@ -0,0 +1,44 @@
+<div id="<%=id%>" class="gluon-osm-map" style="display: none"></div>
+<script type="text/javascript" src="/static/gluon-web-osm.js"></script>
+<script type="text/javascript">
+	(function() {
+		var elMap = document.getElementById(<%=json(id)%>);
+		var wrapper = elMap.parentNode;
+
+		var elLon, elLat;
+		window.addEventListener('gluon-update', function() {
+			<% if self.lon then -%>
+				elLon = document.getElementById(<%=json(self.lon:id())%>);
+			<%- end %>
+			<% if self.lat then -%>
+				elLat = document.getElementById(<%=json(self.lat:id())%>);
+			<%- end %>
+		}, {once: true});
+
+		initOSM(<%=json(self.openlayers_url)%>, function(createMap) {
+			elMap.style.display = '';
+
+			var pos = <%=json(self:cfgvalue().pos)%>;
+			var map = createMap(
+				elMap,
+				[pos.lon, pos.lat],
+				<%=json(self:cfgvalue().zoom)%>,
+				<%=json(self:cfgvalue().set)%>,
+				function(lonlat) {
+					if (elLon) {
+						elLon.value = lonlat[0].toFixed(6);
+						elLon.dispatchEvent(new Event('gluon-revalidate'));
+					}
+					if (elLat) {
+						elLat.value = lonlat[1].toFixed(6);
+						elLat.dispatchEvent(new Event('gluon-revalidate'));
+					}
+				}
+			);
+
+			wrapper.addEventListener('gluon-show', function() {
+				map.updateSize();
+			});
+		});
+	})();
+</script>
diff --git a/package/gluon-web-osm/files/lib/gluon/web/www/static/gluon-web-osm.js b/package/gluon-web-osm/files/lib/gluon/web/www/static/gluon-web-osm.js
new file mode 100644
index 0000000000000000000000000000000000000000..3d85f6f18675f132748660b56479dc2863e69e78
--- /dev/null
+++ b/package/gluon-web-osm/files/lib/gluon/web/www/static/gluon-web-osm.js
@@ -0,0 +1 @@
+"use strict";function initOSM(e,o){var t=document.createElement("link");t.rel="stylesheet",t.type="text/css",t.href=e+"/css/ol.css",document.head.appendChild(t);var n=document.createElement("script"),r=!1;n.onload=n.onreadystatechange=function(){if(!(r||this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)){r=!0;var t=new Image;t.onload=function(){var e=new ol.style.Style({image:new ol.style.Icon({img:t,imgSize:[30,45],anchor:[.5,1]})}),c=new ol.Feature;c.setStyle(e),o(function(e,t,o,n,r){var a=new ol.Map({target:e,layers:[new ol.layer.Tile({source:new ol.source.OSM}),new ol.layer.Vector({source:new ol.source.Vector({features:[c]})})],view:new ol.View({center:ol.proj.fromLonLat(t),zoom:o})}),l=function(e){c.setGeometry(new ol.geom.Point(e))};return a.addEventListener("click",function(e){l(e.coordinate),r(ol.proj.toLonLat(e.coordinate))}),n&&l(ol.proj.fromLonLat(t)),a})},t.src="data:image/svg+xml,"+escape('<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="30" height="45"><path d="M2,15A13,13,0,0,1,28,13Q28,28,15,45Q2,28,2,15" fill="#48b" stroke="#369" stroke-width="1.5" /><circle cx="15" cy="15" r="6" fill="#fff" /></svg>')}},n.src=e+"/build/ol.js",document.head.appendChild(n)}
\ No newline at end of file
diff --git a/package/gluon-web-osm/files/lib/gluon/web/www/static/osm.js b/package/gluon-web-osm/files/lib/gluon/web/www/static/osm.js
deleted file mode 100644
index 6ea2ea0e6d89855da8a305480d2ea3fded55becb..0000000000000000000000000000000000000000
--- a/package/gluon-web-osm/files/lib/gluon/web/www/static/osm.js
+++ /dev/null
@@ -1 +0,0 @@
-function findObj(e){for(list=document.getElementsByClassName("gluon-input-text"),i=0;i<list.length;i++)if(item=list.item(i),0<=item.id.indexOf(e))return item;return!1}function showMap(){if("object"==typeof OpenLayers&&!1!==findObj("longitude")){document.getElementById("locationPickerMap").style.display="block";var a=new OpenLayers.Projection("EPSG:4326"),o=new OpenLayers.Projection("EPSG:900913"),e=zoom,t=new OpenLayers.Layer.Markers("Markers");OpenLayers.Control.Click=OpenLayers.Class(OpenLayers.Control,{defaultHandlerOptions:{single:!0,double:!1,pixelTolerance:0,stopSingle:!1,stopDouble:!1},initialize:function(){this.handlerOptions=OpenLayers.Util.extend({},this.defaultHandlerOptions),OpenLayers.Control.prototype.initialize.apply(this,arguments),this.handler=new OpenLayers.Handler.Click(this,{click:this.trigger},this.handlerOptions)},trigger:function(e){var n=osmMap.getLonLatFromPixel(e.xy);oLon=findObj("longitude"),oLat=findObj("latitude"),lonlat1=new OpenLayers.LonLat(n.lon,n.lat).transform(o,a),oLon.value=lonlat1.lon,oLat.value=lonlat1.lat,t.clearMarkers(),t.addMarker(new OpenLayers.Marker(n)),oLon.className=oLon.className.replace(/ gluon-input-invalid/g,""),oLat.className=oLat.className.replace(/ gluon-input-invalid/g,"")}}),osmMap=new OpenLayers.Map("locationPickerMap",{controls:[new OpenLayers.Control.Navigation,new OpenLayers.Control.PanZoomBar,new OpenLayers.Control.MousePosition],maxExtent:new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),numZoomLevels:18,maxResolution:156543,units:"m",projection:o,displayProjection:a});var n=new OpenLayers.Layer.OSM("OpenStreetMap");osmMap.addLayer(n),osmMap.addLayer(t);var r=longitude,i=latitude;oLon=findObj("longitude"),oLat=findObj("latitude"),""!=oLon.value&&(r=oLon.value),""!=oLat.value&&(i=oLat.value),t.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(r,i).transform(a,o)));var l=new OpenLayers.LonLat(r,i).transform(a,o);osmMap.setCenter(l,e);var s=new OpenLayers.Control.Click;osmMap.addControl(s),s.activate()}else setTimeout(showMap,1e3)}
\ No newline at end of file
diff --git a/package/gluon-web-osm/javascript/gluon-web-osm.js b/package/gluon-web-osm/javascript/gluon-web-osm.js
new file mode 100644
index 0000000000000000000000000000000000000000..65b06e26c89d96fef9e0449c66e7e30bb0f80e7f
--- /dev/null
+++ b/package/gluon-web-osm/javascript/gluon-web-osm.js
@@ -0,0 +1,84 @@
+/*
+	Build using:
+
+	uglifyjs javascript/gluon-web-osm.js -o files/lib/gluon/web/www/static/gluon-web-osm.js -c -m
+*/
+
+'use strict';
+
+function initOSM(openlayers_url, ready) {
+	var markerSvg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="30" height="45">'
+		+ '<path d="M2,15A13,13,0,0,1,28,13Q28,28,15,45Q2,28,2,15" fill="#48b" stroke="#369" stroke-width="1.5" />'
+		+ '<circle cx="15" cy="15" r="6" fill="#fff" />'
+		+ '</svg>';
+
+	var style = document.createElement('link');
+	style.rel = 'stylesheet';
+	style.type = 'text/css';
+	style.href = openlayers_url + '/css/ol.css';
+	document.head.appendChild(style);
+
+	var script = document.createElement('script');
+	var done = false;
+	script.onload = script.onreadystatechange = function() {
+		if (done)
+			return;
+		if (this.readyState && this.readyState !== "loaded" && this.readyState !== "complete")
+			return;
+
+		done = true;
+
+
+		var markerImg = new Image();
+		markerImg.onload = function() {
+			var markerStyle = new ol.style.Style({
+				image: new ol.style.Icon({
+					img: markerImg,
+					imgSize: [30, 45],
+					anchor: [0.5, 1]
+				})
+			});
+
+			var marker = new ol.Feature();
+			marker.setStyle(markerStyle);
+
+			ready(function(elMap, pos, zoom, set, onUpdate) {
+				var map = new ol.Map({
+					target: elMap,
+					layers: [
+						new ol.layer.Tile({
+							source: new ol.source.OSM()
+						}),
+						new ol.layer.Vector({
+							source: new ol.source.Vector({
+								features: [marker]
+							})
+						})
+					],
+					view: new ol.View({
+						center: ol.proj.fromLonLat(pos),
+						zoom: zoom,
+					})
+				});
+
+				var refresh = function(coord) {
+					marker.setGeometry(new ol.geom.Point(coord));
+				}
+
+				map.addEventListener('click', function(e) {
+					refresh(e.coordinate);
+					onUpdate(ol.proj.toLonLat(e.coordinate));
+				});
+
+				if (set)
+					refresh(ol.proj.fromLonLat(pos));
+
+				return map;
+			});
+		}
+
+		markerImg.src = 'data:image/svg+xml,' + escape(markerSvg);
+	};
+	script.src = openlayers_url + '/build/ol.js';
+	document.head.appendChild(script);
+}
diff --git a/package/gluon-web-osm/javascript/osm.js b/package/gluon-web-osm/javascript/osm.js
deleted file mode 100644
index 3aad1f62796745fad92018a25e7cbb982f39b1d5..0000000000000000000000000000000000000000
--- a/package/gluon-web-osm/javascript/osm.js
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-	Build using:
-
-	uglifyjs javascript/osm.js -o files/lib/gluon/web/www/static/osm.js -c -m
-*/
-
-function findObj(name) {
-        list = document.getElementsByClassName("gluon-input-text");
-        for(i = 0; i < list.length; i++) {
-                item = list.item(i);
-                if(item.id.indexOf(name) >= 0) return item;
-        }
-        return false;
-}
-
-function showMap() {
-        if ("object" == typeof OpenLayers && false !== findObj("longitude")) {
-                document.getElementById("locationPickerMap").style.display = "block";
-                var e = new OpenLayers.Projection("EPSG:4326"),
-                        a = new OpenLayers.Projection("EPSG:900913"),
-                        t = zoom,
-                        n = new OpenLayers.Layer.Markers("Markers");
-                OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, {
-                        defaultHandlerOptions: {
-                                single: !0,
-                                "double": !1,
-                                pixelTolerance: 0,
-                                stopSingle: !1,
-                                stopDouble: !1
-                        },
-                        initialize: function() {
-                                this.handlerOptions = OpenLayers.Util.extend({}, this.defaultHandlerOptions), OpenLayers.Control.prototype.initialize.apply(this, arguments), this.handler = new OpenLayers.Handler.Click(this, {
-                                        click: this.trigger
-                                }, this.handlerOptions)
-                        },
-                        trigger: function(t) {
-                                var i = osmMap.getLonLatFromPixel(t.xy);
-                                oLon = findObj("longitude");
-                                oLat = findObj("latitude");
-                                lonlat1 = new OpenLayers.LonLat(i.lon, i.lat).transform(a, e),
-                                        oLon.value = lonlat1.lon,
-                                        oLat.value = lonlat1.lat,
-                                        n.clearMarkers(),
-                                        n.addMarker(new OpenLayers.Marker(i)),
-                                        oLon.className = oLon.className.replace(/ gluon-input-invalid/g, ""),
-                                        oLat.className = oLat.className.replace(/ gluon-input-invalid/g, "");
-                        }
-                }), osmMap = new OpenLayers.Map("locationPickerMap", {
-                        controls: [new OpenLayers.Control.Navigation, new OpenLayers.Control.PanZoomBar, new OpenLayers.Control.MousePosition],
-                        maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
-                        numZoomLevels: 18,
-                        maxResolution: 156543,
-                        units: "m",
-                        projection: a,
-                        displayProjection: e
-                });
-                var i = new OpenLayers.Layer.OSM("OpenStreetMap");
-                osmMap.addLayer(i), osmMap.addLayer(n);
-                var o = longitude,
-                        r = latitude;
-                oLon = findObj("longitude");
-                oLat = findObj("latitude");
-                "" != oLon.value && (o = oLon.value),
-                "" != oLat.value && (r = oLat.value),
-                n.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(o, r).transform(e, a)));
-                var l = new OpenLayers.LonLat(o, r),
-                        d = l.transform(e, a);
-                osmMap.setCenter(d, t);
-                var s = new OpenLayers.Control.Click;
-                osmMap.addControl(s), s.activate()
-        } else setTimeout(showMap, 1e3)
-}
diff --git a/package/gluon-web-osm/luasrc/usr/lib/lua/gluon/web/model/osm.lua b/package/gluon-web-osm/luasrc/usr/lib/lua/gluon/web/model/osm.lua
new file mode 100644
index 0000000000000000000000000000000000000000..138a5ec81fa13458c9b81c45ff22829b3a520e8f
--- /dev/null
+++ b/package/gluon-web-osm/luasrc/usr/lib/lua/gluon/web/model/osm.lua
@@ -0,0 +1,43 @@
+module('gluon.web.model.osm', package.seeall)
+
+local classes = require 'gluon.web.model.classes'
+local util = require "gluon.web.util"
+
+local class = util.class
+
+
+local DEFAULT_URL = 'https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.2.0'
+
+
+MapValue = class(classes.AbstractValue)
+
+function MapValue:__init__(title, options)
+	classes.AbstractValue.__init__(self, title)
+	self.subtemplate  = "model/osm/map"
+	self.openlayers_url = options.openlayers_url or DEFAULT_URL
+	self.lon = options.lon
+	self.lat = options.lat
+
+	self.pos = options.pos or {lon = 0, lat = 0}
+	self.zoom = options.zoom or 0
+	self.set = options.set or false
+end
+
+function MapValue:cfgvalue()
+	local pos_lon = tonumber(self.lon and self.lon:cfgvalue())
+	local pos_lat = tonumber(self.lat and self.lat:cfgvalue())
+
+	if pos_lon and pos_lat then
+		return {
+			zoom = 18,
+			pos = { lon = pos_lon, lat = pos_lat },
+			set = true,
+		}
+	else
+		return self
+	end
+end
+
+function MapValue:validate()
+	return true
+end