walkermatt / ol-popup Goto Github PK
View Code? Open in Web Editor NEWOpenLayers popup overlay
License: MIT License
OpenLayers popup overlay
License: MIT License
The changes required should be fairly small:
src/ol-popup.js
to match ol v5 conventionglobals
in rollup configexamples
in this repo to use v5Hi,
ol3-popup has any event? For example "shown" event.
I'd like to trigger a callback function to run when a popup is displayed using on('popup')
(or something equivalent). Is this currently possible? Or would it be a new feature request?
Perhaps the Popup.show()
function could call dispatchEvent()
to trigger its own event?
https://openlayers.org/en/latest/apidoc/module-ol_Observable-Observable.html#dispatchEvent
Base class ol.Overlay
already contains autoPan
option.
I use ol-popup with OpenLayers 3. For many reasons I can't use stopevent with popup (one of main is that it has quite sophisticated content using Bootstrap stuff etc.), so what I do is I Ol.un() most interactions on 'mouseenter' event adn set them back on 'mouseleave'. Everything worked perfectly for Chrome and Firefox... up to 58. With Firefox 59 wheelscroll still works ok, but trying to scroll popup content with mouse left button ends up with moving the map around.
I'm aware of the fact that this may be to specific, but I have no idea how to even start dealing with it.
Best regards,
r.
Hi!!
How can I do the npm installation for angular use? Have you posted anything on npmjs.com?
Thanks for your time :)
Please include a typescript definition file.
Excuse my daring, I am Spanish, self-taught and a beginner in programming and in GIS, I am building a map for my blog with openlayers, I have learned a lot with their examples and I use their libraries Layerswitcher and ol.popup.
I already have a beautiful map in my blog http://maparutasmtb.blogspot.com/ but the pop-up window, although it works, is not quite right.
I wish show the information of the GPX layer (waypoints) and a marker that I include in the map.
Would you be so kind to help me and tell me where I'm wrong?
This is the Popup code:
var popup = new Popup();
map.addOverlay(popup);
map.on('singleclick', function(evt) {
var info = document.getElementById('info');
var target = document.getElementById('map');
function displayFeatureInfo(pixel) {
info.style.left = pixel[0] + 'px';
info.style.top = (pixel[1] - 1) + 'px';
var feature = map.forEachFeatureAtPixel(pixel, function(feature, layer) {
return feature;
});
if (feature) {
var text = feature.get('desc');
info.style.display = 'none';
info.innerHTML = text;
info.style.display = 'block';
target.style.cursor = "";
} else {
info.style.display = 'none';
map.getTarget().style.cursor = "";
}
}
if (evt.dragging) {
info.style.display = 'none';
return;
}
var pixel = map.getEventPixel(evt.originalEvent);
displayFeatureInfo(pixel);
popup.show(evt.coordinate, info);
});
I have an example running on JSFiddle, where you can see the entire code https://jsfiddle.net/nanoflojo/zd5y4aw3/
Sorry for my bad speaking English and thank you for your attention, a warm greeting, Nacho.
Have you tested this with v6? I'll do so as soon as I can.
I am trying to use Popups on a map I have created and I am having trouble. Popups work fine on the example that I cloned onto my laptop. However, I cannot use it on my own maps. I add the following two lines to my own map.
In the head I add,
<link rel="stylesheet" href="https://raw.githubusercontent.com/walkermatt/ol3-popup/master/src/ol3-popup.css" />
And I add in the body I add
<script src="https://raw.githubusercontent.com/walkermatt/ol3-popup/master/src/ol3-popup.js"></script>
However, I get the ol.Overlay.Popup is not a constructor
error when I do this and add
var popup = new ol.Overlay.Popup(); map.addOverlay(popup);
To the map. I tried using the copying the cloned files into the directory my maps were in but I ended up with the same problem both ways. Any ideas of what is wrong?
Hi!
Thanks for your great popup plugin.
This is related to openlayers/openlayers#7083
I believe the issue should be solved in the OpenLayers core (although architecturally more difficult), but for you it might be easy to write a workaround to fix the following regression.
Since the custom auto-pan code is gone in favour of ol.Overlay.autoPan, my application does not anymore fully work as intended:
When popup content changes after positioning, and the popup size grows due to the changed content, then the map no longer pans to move the popup into its viewport.
The reason is that ol.Overlay.Popup.prototype.show does call ol.Overlay.prototype.setPosition -- but the position change event listener ol.Overlay.prototype.handlePositionChanged (which calls the necessary ol.Overlay.prototype.panIntoView_) is not invoked (because ol.Object.prototype.set checks for oldValue !== value).
Unfortunately, there is no ol.Overlay.prototype.handleSizeChanged, since there is no size change event in OpenLayers - the Overlay size here is manipulated via CSS.
I think what should be done is:
The only method which knows about popup content changes is ol.Overlay.Popup.prototype.show.
Therefore, ol.Overlay.Popup should add its own @protected
helper method (e.g. ol.Overlay.Popup.prototype.handleContentChanged) to gain access to the @protected
ol.Overlay.prototype.handlePositionChanged. (Note: ol.Overlay.prototype.panIntoView_ is unfortunately @private
.)
Within ol.Overlay.Popup.prototype.show, the new ol.Overlay.Popup.prototype.handleContentChanged should be called, which then invokes ol.Overlay.prototype.handlePositionChanged and thus ol.Overlay.prototype.panIntoView_ (if ol.Overlay.autoPan is true).
Thank you for all your work!
Hello @walkermatt,
I'm new to Openlayers and I didn't realize how complicated it its to add an Overlay Popup but thanks to you I can have one very easily.
I noticed that the popup where not on the same exact coordinates when you zoomed in the map (see below). Is there quick fix to this or do you plugin have a solution/workaround for this?
Thanks,
Alexe
Using OL 4.2.0 and last realease of ol3-popup i get an issue here ;
ol.Overlay.call(this, Object.assign(options, {
element: this.container
}));
Object.assign throws :
AssertionError: Assertion failed. See https://openlayers.org/en/v4.2.0/doc/errors/#1 for details
Hey @walkermatt, how about prepare ol3-popup to be hosted on jsDelivr - https://github.com/jsdelivr/jsdelivr/blob/master/CONTRIBUTING.md, if you agree I can create a PR with a build process I use on https://github.com/jonataswalker/ol3-geocoder.
It could much easier to include your ext on a fiddle for instance.
Hi,
It seem that op-popup is compatible with openlayers 7.1.0 but not with 7.5.2.
I think its about the new definition of popup in 7.5.2:
import Overlay from 'ol/Overlay.js';
instead of (7.1.0):
import Overlay from 'ol/Overlay';
I m using Openlayers 5 with APEX ORACLE .
`export default class Popup extends ol.Overlay {
`
Hi matt,
wonderfull extensions you made! Just played aroung with ol3 for the first time and first missings were popups and layer-switcher!
Now, with popup is have no cross to close, but get a cryptic "âoe--"
Is that "sign" font-specific?
What if I want create a popup that can be drag and drop anywhere I want? The official site has a similary popup example by using overlay. But overlay can't be drag. I need to popup a chart, and the chart can be drag and drop or mouse follow-up.
How can I achieve this? Will be glad if you can give me some advise. And sorry for awful English, hope you have no problem understanding me.
I'm trying to figure out the best way to add buttons to your popups. The idea being that the popup has the address of a location and the button would add that feature's address to a route plan. Thoughts?
Actually, rather drop the number altogether, since OpenLayers now uses SemVer, and version numbers should jump up rather quickly.
I see that it is important to make a difference between the old Openlayers 2 popup on one side, and this plugin on the other side. Is there a better way than to keep the now (and in the future) misleading "ol3-popup" name?
The scrollable option doesn't appear to work on mobile.
Hi,
I show popup before my html content. After, i set html string in popup. I want set new popup position on center screen? Anybody can help? Thanks...
Hi Matt,
I have played with your 'ol3-popup'.
I added some additional options like:
They are useful if there different popups necessary.
My result is here: http://www.hareck.lima-city.de/ol3-ls-popup/ol3test.html.
There is one problem, not with the popup, but with ol3: OpenLayers 3 not detecting a feature when over a
transparent pixel of the icon is a feature.
I have opened an issue: Detecting a feature when over a transparent pixel of the icon is a feature (#2961) for discussion.
Thank you for the great layerswitcher and popup implementation.
Hareck
The ol library files all begin with goog.provide(nameOfModule). I think it would make sense for extension developers to make their modules closure compatible I personally dislike the fact that OL3 is build upon closure instead of AMD so a fix like this would be just fine with me:
define(function() {
ol.Overlay.Popup = function(opt_options) {
...
return ol.Overlay.Popup;
});
Hi all,
Sorry for my badly english, i have difficulty speaking english.
I use your code popup.js for my map. It's working with open layer 3.19.1 or less (3.17 / 3.16...).
But in OL3 v 3.20.1 isn't working.
When you clic on the markers, there are no reaction. Indeed, the popup doesn't appear.
There are problem with new version OL3 v3.20.1 ?
Thanks for all answers
Hi I am using the ol-popup javascript
i got an error when i want to update my ol to ol 7
ol-popup.js.download:107 Uncaught TypeError: Class constructor ca cannot be invoked without 'new'
at new Popup (ol-popup.js:107:103)
at popup.js.:14:13
at new Popup (ol-popup.js:107:103) =
var _this = possibleConstructorReturn(this, (Popup.proto || Object.getPrototypeOf(Popup)).call(this, options));
at popup.js.:14:13 =
var popup = new Popup();
Do you have a solution?
For some reason i can't get the popup displayed.
The following is my piece of code.
`
const MarkerLayer = ({ source, zIndex = 0 }) => {
const { map } = useContext(MapContext);
useEffect(() => {
if (!map) return;
var vectorSource = new OLSourceVector({});
var markerVectorLayer = new OLVectorLayer({});
var popup = new Popup({
insertFirst: false,
});
map.addOverlay(popup);
source.features.forEach(element => {
if(element.geometry != null){
var marker = new OLFeature({
geometry: new Point(fromLonLat([element.geometry.coordinates[0], element.geometry.coordinates[1]])),
properties: element.properties,
type: 'click',
});
var iconStyle = new OLStyle({
image: new OLStyleIcon( ({
color: '#f1e7fe',
scale:0.7,
crossOrigin: 'anonymous',
src: 'http://maps.google.com/mapfiles/ms/micons/blue.png'
}))
});
marker.setStyle(iconStyle);
vectorSource.addFeature(marker);
}
});
map.on('singleclick', (evt) => {
var f = map.forEachFeatureAtPixel(
evt.pixel,
function(ft, layer){return ft;}
);
if (f && f.get('type') == 'click') {
var geometry = f.getGeometry();
var coord = geometry.getCoordinates();
// var content = '<p> Building Type: '+f.get('properties').BLD_Type + '</p>' +
// '</br>' + '<p> Issue Date:'+ f.get('properties').ISSUE_DATE + '</p>' +
// '</br>' + '<p> Building Cost:'+ f.get('properties').BLD_Cost + '</p>' +
// '</br>' + '<p> SQFT Floor:'+ f.get('properties').SQFT_FLOOR + '</p>';
console.log(coord);
var el = document.createElement("div");
var title = document.createElement("h2");
title.innerHTML = 'Demolition Details';
el.appendChild(title);
var content = document.createElement("div");
content.innerHTML = '<p> Building Type: '+f.get('properties').BLD_Type + '</p>' +
'</br>' + '<p> Issue Date:'+ f.get('properties').ISSUE_DATE + '</p>' +
'</br>' + '<p> Building Cost:'+ f.get('properties').BLD_Cost + '</p>' +
'</br>' + '<p> SQFT Floor:'+ f.get('properties').SQFT_FLOOR + '</p>';
el.appendChild(content);
popup.show(evt.coordinate, el);
}
})
markerVectorLayer = new OLVectorLayer({
source: vectorSource
});
map.addLayer(markerVectorLayer);
markerVectorLayer.setZIndex(zIndex);
return () => {
if (map) {
map.removeLayer(markerVectorLayer);
}
};
}, [map]);
return (null);
};
export default MarkerLayer;`
opt_options
is not extends olx.OverlayOptions as claimed in README. I'm trying to add id
option:
var popup = new ol.Overlay.Popup({
id: 'myId'
});
popup.getId(); // always undefined
Hi,
I am using Angular 5, since 2 days I am trying to install 'ol-popup' liabrary but I am not able to install this.
Command using for installation: npm install ol-popup --save
It is showing below log:
npm ERR! code ECONNRESET
npm ERR! errno ECONNRESET
npm ERR! network request to https://registry.npmjs.org/ol-popup failed, reason: read ECONNRESET
npm ERR! network This is a problem related to network connectivity.
npm ERR! network In most cases you are behind a proxy or have bad network settings.
npm ERR! network
npm ERR! network If you are behind a proxy, please make sure that the
npm ERR! network 'proxy' config is set properly. See: 'npm help config'
Could you explain it please?
OpenLayers is transitioning to ES6 modules and encouraging the use of a build tool such as Webpack or Rollup. I'm currently working on updating the ol3-layerswitcher
, once I'm happy with the approach we'll need to do the same for ol-popup
.
Hy Matt,
I like your examples very much and I already use your solution for layerswitcher. Now I would like to add a popup also, but I have a problem connecting layerswitcher and popup. Could you possibly help? How to combine layerswitcher.js and scroll.js?
Thank you
Hi Matt,
I find your popup solution really usefull and it is already integrated in my application. Now I have a question about visbility. All my layers are defined before I use a popup window. I expect that the popup window will appear on top of all my other layers, but it does not. It is below some other overlay layer. How can I define that your popup window is on top of all other layers?
Kind regards
Guido
I search for a solution to fill the Popup with content from a ajax request, without JQuery. The problem is, in this moment i must send all the content for all the popups by the first call of the website. That is too much data. I will fill the Popup on the click event with data from the server. The content for the Popup come from a xhttp request. Thats not so easy, because a xhttp request don't return a value.
A little bit of my code:
myscript.js
var feature = new ol.Feature({
type: 'click',
desc: descriptionstring,
geometry: new ol.geom.Point(ol.proj.fromLonLat(coordarray_coordinate))
});
feature.setStyle(stylecircle);
sourceVector.addFeature(feature);
}
ol-popup.js (old)
ol.Overlay.Popup.prototype.show = function(coord, html) {
this.setPosition(coord);
// is here the right place for a xhttp request?
// var xmlhttp = new XMLHttpRequest();
// xmlhttp.onreadystatechange = function() {
// if (this.readyState == 4 && this.status == 200) {
// html = this.responseText;
this.content.innerHTML = html;
// }
// };
// xmlhttp.open("GET", "gethint.php?q=" + str, true);
// xmlhttp.send();
// ------------------------------------------
this.container.style.display = 'block';
var content = this.content;
window.setTimeout(function(){
content.scrollTop = 0;
}, 100);
if (this.panMapIfOutOfView) {
this.panIntoView_(coord);
}
return this;
};
Or why in the new ol-popup.js code?
Hello, first of all many thank for this plugin, it helps a lot. We have been using your plugin in our project. However for some needs we had to extent it, successfully, on several aspects, that i here list below:
We would not like to let this as fork, but rather to contribute it. Let me know if you are interested, in which case i could do it as proper fork in github, and pull request to share with you.
Best,
Emmanuel
Hi Matt!
It would be great if a click on a second feature shows the popup for that feature, but also keeps the first popup open. What I mean is that currently only one popup can be shown. Can this new behaviour be implemented?
Kind regards,
Hi @walkermatt, this is not really an issue but more a tutorial.
For many times i have modded your OL Popup script with an XMLHttpRequest (Ajax):
#217
This i am used in a few of my OSM OL websites.
Yet i had a problem, when the Ajax content have HTML and Javascript inside. More specifically, I had the problem of editing the popup content after insertion (innerHTML successfully completed) via javascript.
I am currently creating such an Ajax popup map, which can also be used by others. The idea is that data stored on the server is loaded into the popup via Ajax and can then also be edited there via Javascript. Example:
One of the data consists of a number (0-100). This number is to be converted by Javascript (Object) into a word. {"0": "word"}
. Now I had thought that I embed a javascript function in the popup HTML content that is created on the server. Which will be triggered as soon as the popup content is loaded. But this does not work without further effort.
But there is a problem. Javascript code that is embedded in HTML code and sent via Ajax and inserted via innerHTML
is not executed. There is one exception: Pure javascript code written inside eval()
and inserted via Ajax and innerHTML
will be executed.
It is possible to realize the thing without executing 2 x XMLHttpRequest - with HTML code and Javascript code separately. For this the OL popup code must be extended a bit.
The thing is that I don't know how an OL Popup Ajax Map user wants to edit the popup content with javascript. He could already adjust the HTML content via PHP, but that's going too far, because I don't want users to edit in the (Ajax) PHP code.
I made the whole map software as simple as possible. It is a bit complex, but not more than necessary.
I made the Ajax PHP code very simple. There is a single text file, which can be used to control the rough structure (order) of the arrangement of the data in the popup. Furthermore there is a custom-style.css
which can be used to style the popup content.
It would be possible to execute the custom-style javascript code using setInterval()
and clearInterval()
. So by checking when the popup content is completely loaded, and then the custom-style JS code is executed. I had already coded this, but I didn't like it.
I came across eval()
while searching. However, this has to be included absolutely separately via Ajax and innnerHTML
- with a single XMLHttpRequest.
The solution is to extend the ol-popup script and append an additional div-box ol-popup-content-customscript
(with display:none
) to the div-box ol-popup
. Into this additional div-box a eval()
is inserted via popup.show
while filling the popup via Ajax. This eval()
triggers a function
- the custom-style function - eval(typeof popuploadcustomscript === 'function' ? popuploadcustomscript() : 'ERROR')
. The function popuploadcustomscript
is located in the file custom-style.js
, and inside the function the user javascript code.
The div-box ol-popup-content-customscript
gets display:none
, because eval()
inserts an undefined
.
index.html/php
<script src="custom-style.js"></script>
custom-style.js
function popuploadcustomscript() {
// user-created Javascript code here, like ... {"0": "word"}
}
ol-popup-400.js (expanded code places)
var element = document.createElement('div');
options.element = element;
var _this = possibleConstructorReturn(this, (Popup.__proto__ || Object.getPrototypeOf(Popup)).call(this, options));
_this.container = element;
_this.container.className = 'ol-popup';
_this.closer = document.createElement('a');
_this.closer.className = 'ol-popup-closer';
_this.closer.href = '#';
_this.container.appendChild(_this.closer);
var that = _this;
_this.closer.addEventListener('click', function (evt) {
that.container.style.display = 'none';
that.closer.blur();
evt.preventDefault();
}, false);
_this.content = document.createElement('div');
_this.content.className = 'ol-popup-content';
_this.container.appendChild(_this.content);
// ### CUSTOMSCRIPT CODE ↓↓↓
_this.content_customscript = document.createElement('div');
_this.content_customscript.className = 'ol-popup-content-customscript';
_this.container.appendChild(_this.content_customscript);
// ### CUSTOMSCRIPT CODE ↑↑↑
// ...
value: function show(coord, html) {
if (html instanceof HTMLElement) {
this.content.innerHTML = "";
this.content.appendChild(html);
// ### CUSTOMSCRIPT CODE ↓↓↓
this.content_customscript.innerHTML = eval(typeof popuploadcustomscript === 'function' ? popuploadcustomscript() : 'ERROR');
// ### CUSTOMSCRIPT CODE ↑↑↑
} else {
this.content.innerHTML = html;
// ### CUSTOMSCRIPT CODE ↓↓↓
this.content_customscript.innerHTML = eval(typeof popuploadcustomscript === 'function' ? popuploadcustomscript() : 'ERROR');
// ### CUSTOMSCRIPT CODE ↑↑↑
}
this.container.style.display = 'block';
this.content.scrollTop = 0;
this.setPosition(coord);
return this;
}
Thats all!
When the popup content is loaded completely, the custom-style Javascript will be executed.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.