gluon-web-osm: base on OpenLayers 5, add model class
The new code is shorter and uses more readable variable names. It does not depend on specifically named input fields anymore (allowing to use multiple maps on the same page), and only uses well-defined interfaces to trigger revalidation of input fields. The Map model class allows to add OSM maps to gluon-web forms.
This commit is contained in:
parent
ba1df47dba
commit
0d4188d40b
File diff suppressed because one or more lines are too long
@ -284,6 +284,12 @@ code {
|
|||||||
margin-bottom: 2em;
|
margin-bottom: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gluon-osm-map {
|
||||||
|
width: 100%;
|
||||||
|
height: 40em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
input:placeholder {
|
input:placeholder {
|
||||||
color: #aaaaaa;
|
color: #aaaaaa;
|
||||||
}
|
}
|
||||||
|
@ -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>
|
@ -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)}
|
@ -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)}
|
|
84
package/gluon-web-osm/javascript/gluon-web-osm.js
Normal file
84
package/gluon-web-osm/javascript/gluon-web-osm.js
Normal file
@ -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);
|
||||||
|
}
|
@ -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)
|
|
||||||
}
|
|
@ -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
|
Loading…
Reference in New Issue
Block a user