Skip to content

Instantly share code, notes, and snippets.

@ThomasG77
Last active October 16, 2017 22:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ThomasG77/77bee632812a3441a72eb534603930a6 to your computer and use it in GitHub Desktop.
Save ThomasG77/77bee632812a3441a72eb534603930a6 to your computer and use it in GitHub Desktop.
Vanilla JS fork of ol3-ext GeoBookmark http://bl.ocks.org/ThomasG77/77bee632812a3441a72eb534603930a6 (original version at http://viglino.github.io/ol3-ext/examples/map.control.geobookmark.html) due to jQuery dependency
/** GeoBookmarks
*
* @constructor
* @extends {ol.control.Control}
* @trigger add|remove when a bookmark us added or deleted
* @param {Object=} Control options.
* - className {string} default ol-bookmark
* - placeholder {string} input placeholder, default Add a new geomark...
* - editable {bool} enable modification, default true
* - marks a list of default bookmarks : { BM1:{pos:ol.coordinates, zoom: integer, permanent: true}, BM2:{pos:ol.coordinates, zoom: integer} }
*/
ol.control.GeoBookmark = function(options) {
options = options || {};
var self = this;
var element = document.createElement('div');
if (options.target) {
element.className = options.className || "ol-bookmark";
} else {
element.className = (options.className || "ol-bookmark") +
" ol-unselectable ol-control ol-collapsed";
element.addEventListener("mouseleave", function() {
if (input !== document.activeElement) {
menu.style.display = 'none';
};
});
// Show bookmarks on click
this.button = document.createElement('button');
this.button.setAttribute('type', 'button');
this.button.addEventListener('click', function(e) {
menu.style.display = (menu.style.display === '' || menu.style.display === 'none' ? 'block': 'none');
});
element.appendChild(this.button);
}
// The menu
var menu = document.createElement('div');
element.appendChild(menu);
var ul = document.createElement('ul');
menu.appendChild(ul);
var input = document.createElement('input');
input.setAttribute("placeholder", options.placeholder || "Add a new geomark...")
input.addEventListener("change", function(e) {
console.log('change', this);
var title = this.value;
if (title) {
self.addBookmark(title);
this.value = '';
self.dispatchEvent({
type: "add",
name: title
});
}
menu.style.display = 'none';
});
input.addEventListener("blur", function() {
menu.style.display = 'none';
});
if (options.editable !== false) {
menu.appendChild(input);
};
// Init
ol.control.Control.call(this, {
element: element,
target: options.target
});
this.set("editable", options.editable !== false);
// Set default bmark
this.setBookmarks(options.marks);
};
ol.inherits(ol.control.GeoBookmark, ol.control.Control);
/** Set bookmarks
* @param {} bmark a list of bookmarks : { BM1:{pos:ol.coordinates, zoom: integer}, BM2:{pos:ol.coordinates, zoom: integer} }
* @param [boolean} modify, default false
*/
ol.control.GeoBookmark.prototype.setBookmarks = function(bmark) {
if (!bmark) bmark = JSON.parse(localStorage["ol@bookmark"] || "{}");
var modify = this.get("editable");
var ul = this.element.querySelector("ul");
var menu = this.element.querySelector("div");
var self = this;
localStorage["ol@bookmark"] = JSON.stringify(bmark);
// ul.innerHtml = '';
Array.prototype.slice.call(ul.querySelectorAll('li')).forEach(function(li) {
li.remove();
});
for (var b in bmark) {
var li = document.createElement('li');
li.textContent = b;
li.setAttribute('data-bookmark', JSON.stringify(bmark[b]));
li.addEventListener('click', function() {
var bm = JSON.parse(this.getAttribute("data-bookmark"));
self
.getMap()
.getView()
.setCenter(bm.pos);
self
.getMap()
.getView()
.setZoom(bm.zoom);
menu.style.display = 'none';
});
ul.appendChild(li);
if (modify && !bmark[b].permanent) {
var button = document.createElement('button');
button.setAttribute('data-name', b);
button.setAttribute("title", "Suppr.");
button.addEventListener('click', function(e) {
self.removeBookmark(this.getAttribute("data-name"));
self.dispatchEvent({ type: "add", name: this.getAttribute("data-name") });
e.stopPropagation();
});
li.appendChild(button);
}
}
};
/** Get Geo bookmarks
* @return a list of bookmarks : { BM1:{pos:ol.coordinates, zoom: integer}, BM2:{pos:ol.coordinates, zoom: integer} }
*/
ol.control.GeoBookmark.prototype.getBookmarks = function() {
return JSON.parse(localStorage["ol@bookmark"] || "{}");
};
/** Remove a Geo bookmark
* @param {string} name
*/
ol.control.GeoBookmark.prototype.removeBookmark = function(name) {
if (!name) {
return;
};
bmark = JSON.parse(localStorage["ol@bookmark"] || "{}");
delete bmark[name];
this.setBookmarks(bmark);
};
/** Add a new Geo bookmark
* @param {string} name
* @param {ol.Coordintes} position, default current position
* @param {number} zoom, default default map zoom
* @param {bool} permanent: prevent from deletion, default false
*/
ol.control.GeoBookmark.prototype.addBookmark = function(
name,
position,
zoom,
permanent
) {
if (!name) return;
bmark = JSON.parse(localStorage["ol@bookmark"] || "{}");
bmark[name] = {
pos:
position ||
this.getMap()
.getView()
.getCenter(),
zoom:
zoom ||
this.getMap()
.getView()
.getZoom()
};
if (permanent) {
bmark[name].permanent = true;
}
this.setBookmarks(bmark);
};
.ol-control.ol-bookmark
{ top: 0.5em;
left: 3em;
}
.ol-control.ol-bookmark button
{ position: relative;
}
.ol-control.ol-bookmark > button::before
{ content: "";
position: absolute;
border-width: 10px 5px 4px;
border-style: solid;
border-color: #fff;
border-bottom-color: transparent;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
height: 0;
}
.ol-control.ol-bookmark > div
{ display: none;
min-width: 5em;
}
.ol-control.ol-bookmark input
{ font-size: 0.9em;
margin: 0.1em 0 ;
padding: 0 0.5em;
}
.ol-control.ol-bookmark ul
{ margin:0;
padding: 0;
list-style: none;
}
.ol-control.ol-bookmark li
{ color: rgba(0,60,136,0.8);
font-size: 0.9em;
padding: 0 0.2em 0 0.5em;
cursor: default;
clear:both;
}
.ol-control.ol-bookmark li:hover
{ background-color: rgba(0,60,136,.5);
color: #fff;
}
.ol-control.ol-bookmark > div button
{ width: 1em;
height: 0.8em;
float: right;
background-color: transparent;
cursor: pointer;
border-radius: 0;
}
.ol-control.ol-bookmark > div button:before
{ content: "\2A2F";
color: #936;
font-size: 1.2em;
line-height: 1em;
border-radius: 0;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name=description content="">
<meta name=viewport content="width=device-width, initial-scale=1">
<title>Simple OpenStreetMap Map</title>
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://openlayers.org/en/v4.4.1/build/ol.js" type="text/javascript"></script>
<link rel="stylesheet" href="https://openlayers.org/en/v4.4.1/css/ol.css">
<!-- Vanilla fork of ol3-ext GeoBookmark http://viglino.github.io/ol3-ext/examples/map.control.geobookmark.html -->
<script src="geo-bookmarks.js"></script>
<link rel="stylesheet" href="geobookmarkcontrol.css" type="text/css" />
<style type="text/css">
html, body {
margin: 0;
height: 100%;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id="map" class="map">
</div>
<script>
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
var bm = new ol.control.GeoBookmark({
marks: {
"Paris": {
pos: ol.proj.fromLonLat([2.351828, 48.856578]),
zoom: 11,
permanent: true
},
"London": {
pos: ol.proj.fromLonLat([-0.1275,51.507222]),
zoom: 11,
permanent: true
},
"Geneve": {
pos: ol.proj.fromLonLat([6.149985,46.200013]),
zoom: 13,
permanent: true
},
"Bruxelles": {
pos: ol.proj.fromLonLat([4.35,50.83]),
zoom: 12,
permanent: true
},
"Madrid": {
pos: ol.proj.fromLonLat([-3.683333,40.433333]),
zoom: 12
},
"Roma": {
pos: ol.proj.fromLonLat([12.48657,41.888732]),
zoom: 12
}
}
});
map.addControl(bm);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment