Creating popup window and displaying data - javascript

I'm moving from OpenLayers 2 to OpenLayers 6 in my project.
In the OpenLayers 2 project when I click on a feature in a
vector layer I get the description of the feature in a popup window.
Here is the code:
function createVectorLayer(layer) {
var l = new OpenLayers.Layer.Vector(
layer.Title,
{
eventListeners: {
'featureselected': function (evt) {
var f = evt.feature;
var popup = new OpenLayers.Popup.FramedCloud("popup",
//OpenLayers.LonLat.fromString(f.geometry.toShortString()),// Michael commented 25/02/2018
OpenLayers.LonLat.fromString(f.geometry.getCentroid().toShortString()),
null,
"<div style='font-size:.8em'>" + f.attributes.Description + "<br/><a href='#picturedFeatureEditor' class='ui-btn ui-mini' id='featureEditButton'>עדכון</a></div>",
null,
true
);
f.popup = popup;
map.addPopup(popup);
$("#featureEditButton").click(function () {
editableFeature = f.attributes;
editableFeatureObject = f;
initFeatureEditor();
//$.mobile.changePage("#picturedFeatureEditor");
});
},
'featureunselected': function (evt) {
var feature = evt.feature;
map.removePopup(feature.popup);
feature.popup.destroy();
feature.popup = null;
}
},
}
);
return l;
}
Here is how I create a Vector layer in OpenLayers 6:
function createVectorLayer(layer) {
var source = new ol.source.Vector({
loader: dataServices.getFeatures(layer.Id,
function (response) {
if (!response) return;
var features = [];
$(response).each(function (i, j) {
let shapeObject = getShapeObject(j);
let feature = new ol.Feature({ 'geometry': shapeObject });
features.push(feature);
});
source.addFeatures(features);
},
function (jqXhr, textStatus, errorMessag) {
console.log(errorMessag);
})
});
return new ol.layer.Vector({
source: source,
style: createStyle(source)
});
}
I know that I can create a popup using Overlay and ol.interaction.Select
which is fired when the feature is clicked, but I don't know how to access the feature description when the feature is clicked to display it in the popup.
My question is how I can implement the same behaviour using OpenLayers 6 (i.e. how to implement feature popups in 6)?

You can add properties to the feature in the constructor (assuming the data is available from your dataServices):
let feature = new ol.Feature({
geometry: shapeObject,
description: ....
});
which can then be accessed using feature.get('description') or feature.getProperties().description
If you are using a Select interaction
select.on('select', function(event) {
if (event.selected.length > 0) {
var feature = event.selected[0];
var description = feature.get('description');
}
});

You can look at the ol-ext FeaturePopup.
See example: https://viglino.github.io/ol-ext/examples/popup/map.popup.feature.html
Or https://viglino.github.io/ol-ext/examples/popup/map.popup.html

Related

Show InfoWindo with ArcGis Api

Hello everyone I m actually work on geographic application with ArcGsi JavaScript API and I am looking for method that is run when user click on suggestion Menu in the Search Bar for show a Specific
feature InfoWindow
There are a few ways.
First mouse drag options;
var services = new FeatureLayer("http://blablabla/MapServer/0", {
// mode: FeatureLayer.MODE_SNAPSHOT,
// infoTemplate: popupTemplate,
outFields: ["NAME", "ID", "VALUE"]
});
services.on("mouse-over", function (evt) {
var t = "<div class='title'><b>${NAME}</b></div><p>${ID}<br>${VALUE}<br>${VALUE}<br><strong>value: </strong>${VALUE}</p>";
var content = esriLang.substitute(evt.graphic.attributes, t);
//var highlightGraphic = new Graphic(evt.graphic.geometry, highlightSymbol);
//map.graphics.add(highlightGraphic);
dialog.setContent(content);
domStyle.set(dialog.domNode, "opacity", 1);
dijitPopup.open({
popup: dialog,
x: evt.pageX,
y: evt.pageY
});
});
services.on("mouse-out", function (evt) {
closeDialog();
});
Or second away. Click to graphic;
var services = new FeatureLayer("http://blablabla/MapServer/0", {
mode: FeatureLayer.MODE_SNAPSHOT,
// infoTemplate: popupTemplate,
outFields: ["NAME", "ID", "VALUE"]
});
services.on("click", function (evt) {
var name = evt.graphic.attributes.NAME;
var value = evt.graphic.attributes.VALUE;
// your custom html
$("#SevicesContainer").collapse("show");
$("#SevicesContainer").draggable({ containment: "map", scroll: false });
$("#SevicesContainer .close").click(function () {
$("#SevicesContainer").collapse("hide");
});
});

Show the attribute inspector without saving a new feature

The requirement is to add a new feature from template picker but without applying it, can i show the attribute inspector than save the feature.
selectedTemplate = templatePicker.getSelected();
This selectedTemplate is then selected to put the points on the map than opens the attribute inspector by selecting it.
selectedTemplate.featureLayer.applyEdits([newGraphic], null, null);
Sample Code Block :
dojo.connect(drawToolbar, "onDrawEnd", function(geometry) {
//display the editable info window for newly created features
if (map.infoWindow.isShowing) {
map.infoWindow.hide();
}
drawToolbar.deactivate();
var fieldAttributes = layerFieldToAttributes(selectedTemplate.featureLayer.fields);
var newAttributes = dojo.mixin(fieldAttributes, selectedTemplate.template.prototype.attributes);
var newGraphic = new esri.Graphic(geometry, null, newAttributes);
var layerInfos = [{
'featureLayer': selectedTemplate.featureLayer,
'isEditable': true
}];
var attInspector = new esri.dijit.AttributeInspector({
layerInfos: layerInfos
}, dojo.create("div"));
selectedTemplate.featureLayer.applyEdits([newGraphic], null, null, function() {
var screenPoint = map.toScreen(getInfoWindowPositionPoint(newGraphic));
map.infoWindow.setContent(attInspector.domNode);
map.infoWindow.resize(325, 185);
map.infoWindow.show(screenPoint, map.getInfoWindowAnchor(screenPoint));
templatePicker.clearSelection();
});
dojo.connect(attInspector, "onAttributeChange", function(feature, fieldName, newFieldValue) {
feature.attributes[fieldName] = newFieldValue;
feature.getLayer().applyEdits(null, [feature], null);
});
dojo.connect(attInspector, "onDelete", function(feature) {
feature.getLayer().applyEdits(null, null, [feature]);
map.infoWindow.hide();
});
});
}
I would like my client first add the attribute to feature and (save & apply) it.
Any help would be appreciated.
Here is the sample project : https://www.dropbox.com/s/fh71g1k9nsa70nq/index-2.html.zip?dl=0
I dont think you can do that with the AttributeInspector, try creating a custom popup that will have options to save and delete/cancel, when saving fire the applyEdits, when clicking delete, remove, ect.
Content:
var content = "<input id='text1'></input> </br>" +
"<input id='text1'></input> </br>" + "<button id='submit'>Submit</button>" + "<button id='delete'>Delete</button>"
/*
var attInspector = new AttributeInspector({
layerInfos: layerInfos
}, dojo.create("div"));
*/
map.infoWindow.setTitle(selectedTemplate.featureLayer.name);
map.infoWindow.setContent(content);
map.infoWindow.resize(350, 240);
map.infoWindow.show(evt.geometry, map.getInfoWindowAnchor(evt.geometry));
Listener:
on(map.infoWindow, "show", function () {
on(dom.byId("submit"), "click", function () {
alert("I should be saving");
});
on(dom.byId("delete"), "click", function () {
alert("I should be deleting");
});
})
Check out this fiddler: https://jsfiddle.net/kreza/jpLj5y4h/2/

Mapbox handle multiple GEOJSON files with loadURL

I'm currently working on a map that's meant to load multiple layers from different sources based on a config.json file.
Each layer should also display a popup on click but for some reason I only get the popup for the last loaded layer.
I'm using the ready event on the layers to make sure all the data gets loaded and iterating through them using .eachLayer method before binding the popup but still no success and can't figure out what am I missing.
Please find below my code as well a reproduction on: plnkr.co
var myMap = function(options) {
var self = this;
this.settings = $.extend({
layersConfig: 'config.json',
layerData: 'layer',
accessToken: 'pk.eyJ1IjoibWF0dGJsaXNzIiwiYSI6ImNpb3dwczBwZjAwOTh3OWtqOWZ1aG5ob3gifQ.Ot6GdtKew9u27TROm_4A6Q'
}, options);
this.map;
this.layers;
$.ajax({
url: this.settings.layersConfig,
cache: true
}).done(function(data) {
self.init(data);
});
};
myMap.prototype = {
init: function(data) {
var self = this,
settings = this.settings;
L.mapbox.accessToken = settings.accessToken;
var map = this.map = L.mapbox.map('map', 'mapbox.streets')
.setView([54.6, -2.3], 4);
var popup = new L.Popup({
minWidth: 250
});
for (var i = 0; i < data.length; i++) {
var featureLayers = this.layers = L.mapbox.featureLayer(null, {
style: {
weight: 2,
color: data[i].color,
fillColor: data[i].color,
fillOpacity: 0.4
}
}).addTo(map);
// load layers data
featureLayers.loadURL(settings.layerData + data[i].layerId + '.json')
.on('ready', function(e) {
featureLayers.eachLayer(function(layer) {
// cache layer properties
var layerProps = layer.feature.properties;
// cache feature bounds
var bounds = layer.getBounds().toBBoxString();
// bind modal
layer.bindPopup(showPopup(layer, bounds));
});
});
}
map.on('popupopen', function() {
$('.zoom-to').on('click', function() {
var array = $(this).data('zoom').split(',');
map.fitBounds([
[array[1], array[0]],
[array[3], array[2]]
])
});
});
function showPopup(popup, bounds) {
var popupData = popup.feature.properties;
var popupLabel = popupData.NAME;
var popupStructure = '<div class="leaflet-popup-label">' + popupLabel + '</div><button class="zoom-to" data-zoom="' + bounds + '">Zoom to</button></div>'
return popupStructure;
}
}
}
var map = new myMap();
.on('ready',...)
^ Has nothing to do with an AJAX call.
You need to perform actions after the ajax call is finished, that is, inside the AJAX callback.
Here:
}).done(function(data) {
/* do stuff */
});
Found the issue.
Just replace featureLayers.eachLayer with e.target.eachLayer and the popup will show as desired.

Google Map AddListener issue

I have written following code.. which fires Add Listener event on Place_change but i want to fire that event on page load.. which is copied from google and i have made some changes.
function _initMap(latlng){
// google map
$map = $(".lwizard-step1-map");
_latlng = latlng || new google.maps.LatLng(41.3833333,2.1833333);
if (!_STEP1_LOCATION_MAP) {
_STEP1_LOCATION_MAP = new google.maps.Map($map[0],{
center: _latlng,
zoom:11,
mapTypeId:google.maps.MapTypeId.ROADMAP,
streetViewControl:false,
scrollwheel:false
});
} else {
_STEP1_LOCATION_MAP.setCenter(_latlng);
}
if (!_STEP1_LOCATION_MARKER) {
_STEP1_LOCATION_MARKER = new google.maps.Marker({
position: _latlng,
map: _STEP1_LOCATION_MAP,
draggable: true
});
google.maps.event.addListener(_STEP1_LOCATION_MARKER, "dragend", function(event) {
var lat = event.latLng.lat();
var lng = event.latLng.lng();
$("#lwizard-step1-location-autocomplete").val('');
STEP1_PLACE.latLng = [lat,lng];
STEP1_PLACE.address = null;
$.ajax({
url: 'http://maps.googleapis.com/maps/api/geocode/json?latlng='+lat+','+lng+'&sensor=false',
success: function(response){
if ((response) && (response.results) && (response.results.length)){
$(".lwizard-step1-chosen-address").parent().show();
var $address = $(".lwizard-step1-chosen-address");
$address.text(response.results[0].formatted_address);
$("#lwizard-step1-adjust-onmap").data("location", response.results[0].geometry.location);
STEP1_PLACE.address = nc.utils.convertGoogleAddressComponents(response.results[0].address_components);
}
}
})
});
} else {
_STEP1_LOCATION_MARKER.setPosition(_latlng);
}
}
// autocomplete
$input = $("#lwizard-step1-location-autocomplete");
_STEP1_LOCATION_GA = new google.maps.places.Autocomplete($input[0],{ types: [] });
google.maps.event.addListener(_STEP1_LOCATION_GA, 'place_changed', function () {
var place = _STEP1_LOCATION_GA.getPlace();
console.log(place)
var $where = $(".lwizard-step1-chosen-address");
var found = ((place) && (place.formatted_address) && (place.geometry) && (place.id));
if (place && found) {
$("#lwizard-step1-adjust-onmap").data("location", place.geometry.location);
STEP1_PLACE.address = nc.utils.convertGoogleAddressComponents(place.address_components);
STEP1_PLACE.latLng = [place.geometry.location.lat(),place.geometry.location.lng()];
STEP1_PLACE.location = place.geometry.location;
$where.parent().show();
$where.text(place.formatted_address);
$("#lwizard-step1-right-1").show();
$("#lwizard-step1-right-2").hide();
_initMap(place.geometry.location);
} else {
$where.parent().hide();
$("#lwizard-step1-right-1").show();
$("#lwizard-step1-right-2").hide();
_initMap();
}
});
I have one textbox named lwizard-step1-location-autocomplete which shows value from session named SessionLocation on page load.
but i also want to show the map on page load of the location specified in textbox.
But the problem is the addlistener fires only on textbox change means Place_changed event.
pls. Give some suggestions or new method for it.
You can just call change event on load and than it will fired.
$('#lwizard-step1-location-autocomplete').trigger("change");
Or with js;
document.getElementById('lwizard-step1-location-autocomplete').fireEvent("onchange");

OpenLayers - how to use single and double click event on feature

I am using Opnelayers control for selection of feature
OpenLayers.Control.SelectFeature
when I triggered the single click event then feature get selected and its working fine for me. Now I want to use double click event for another operation.
I have get the idea from this link feature to have both a single click and double click event?
I have used the same code and both click events working fine but I cannot get the feature on which click event performed. This is the code
handler = new OpenLayers.Handler.Click(
select,
{
click: function(evt)
{
var feature = this.layer.getFeatureFromEvent(evt);
console.log(feature); // output null
if(this.layer.selectedFeatures){
this.unselect(this.layer.selectedFeatures[0]);
}
},
dblclick: function(evt)
{
// some other operation
}
},
{
single: true,
double: true,
stopDouble: true,
stopSingle: true
}
);
handler.activate();
Any idea which thing is missing in this code?
Thank you
For The Above Question this might solve your answer with few changes
var handler = new OpenLayers.Handler.Click(
layerName, {
click: function(evt) {
console.log('click has triggered');
var feature = layerName.getFeatureFromEvent(evt);
}
,dblclick: function(evt) {
console.log('dblclick has triggered');
}
},{
single: true
,double: true
,stopSingle: true
,stopDouble: true
}
);
handler.activate();
I have been in a similar situation and used the getClosestFeatureToCoordinate method of the layer source. The code would be something like:
click: function(evt) {
var coord = evt.coordinate;
var source = this.layer.getSource();
var feature = source.getClosestFeatureToCoordinate(coord);
// do something with feature
}
I have done in this way.
click: function(evt) {
var pos = map.getLonLatFromPixel(xy);
var point = new OpenLayers.Geometry.Point(pos.lon, pos.lat);
var list = $.map(this.layer.features, function(v) {
return v.geometry.distanceTo(point);
}); // get distance of all features
var min = (Math.min.apply(null, list)); // minimum distance
var closest = $.map(this.layer.features, function(v) {
if (v.geometry.distanceTo(point) == min)
return v;
});
feature = closest[0];
}

Categories

Resources