I'm trying to work with leaflet and leaflet-draw on my react project but i keep getting an error message when I click on delete in the draw pannel even thaugh the edit button and event work fine
here is the code `
const script = document.createElement("script");
script.src =
"https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.2/leaflet.draw.js";
script.async = true;
document.body.appendChild(script);
var map = L.map("map").setView([36.8299552, 10.3194016], 14);
L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
attribution:
'© OpenStreetMap contributors',
}).addTo(map);
// FeatureGroup is to store editable layers
var drawnItems = new L.FeatureGroup();
map.addLayer(drawnItems);
var drawControl = new L.Control.Draw({
draw: {
marker: false,
rectangle: false,
circle: false,
polyline: false,
circlemarker: false,
},
edit: {
featureGroup: drawnItems,
},
});
map.addControl(drawControl);
//draw event
map.on(L.Draw.Event.CREATED, (e) => {
var type = e.layerType,
layer = e.layer;
// Do whatever else you need to. (save to db; add to map etc)
map.addLayer(layer);
drawnItems.addLayer(layer);
if (type == "polygon") {
add_microzone_service({ _latlngs: layer._latlngs });
}
});
map.on("draw:edited", function (e) {
var layers = e.layers;
layers.eachLayer(function (layer) {
console.log(layer.options._id);
});
});
map.on("draw:deleted", function (e) {
var layers = e.layers;
layers.eachLayer(function (layer) {
console.log("deleted");
});
});
and here is the error I'm getting:
Can someone help?
Related
How to prevent the suggestedResult from collapsing after clicking result using SearchWidget?
CodePen, copied below
// An open data address search API for France
const url = "https://api-adresse.data.gouv.fr/";
const map = new Map({
basemap: "streets-vector"
});
const view = new MapView({
container: "viewDiv",
map: map,
center: [2.21, 46.22], // lon, lat
scale: 3000000
});
const customSearchSource = new SearchSource({
placeholder: "example: 8 Boulevard du Port",
// Provide a getSuggestions method
// to provide suggestions to the Search widget
getSuggestions: (params) => {
// You can request data from a
// third-party source to find some
// suggestions with provided suggestTerm
// the user types in the Search widget
return esriRequest(url + "search/", {
query: {
q: params.suggestTerm.replace(/ /g, "+"),
limit: 6,
lat: view.center.latitude,
lon: view.center.longitude
},
responseType: "json"
}).then((results) => {
// Return Suggestion results to display
// in the Search widget
return results.data.features.map((feature) => {
return {
key: "name",
text: feature.properties.label,
sourceIndex: params.sourceIndex
};
});
});
},
// Provide a getResults method to find
// results from the suggestions
getResults: (params) => {
// If the Search widget passes the current location,
// you can use this in your own custom source
const operation = params.location ? "reverse/" : "search/";
let query = {};
// You can perform a different query if a location
// is provided
if (params.location) {
query.lat = params.location.latitude;
query.lon = params.location.longitude;
} else {
query.q = params.suggestResult.text.replace(/ /g, "+");
query.limit = 6;
}
return esriRequest(url + operation, {
query: query,
responseType: "json"
}).then((results) => {
// Parse the results of your custom search
const searchResults = results.data.features.map((feature) => {
// Create a Graphic the Search widget can display
const graphic = new Graphic({
geometry: new Point({
x: feature.geometry.coordinates[0],
y: feature.geometry.coordinates[1]
}),
attributes: feature.properties
});
// Optionally, you can provide an extent for
// a point result, so the view can zoom to it
const buffer = geometryEngine.geodesicBuffer(
graphic.geometry,
100,
"meters"
);
// Return a Search Result
const searchResult = {
extent: buffer.extent,
feature: graphic,
name: feature.properties.label
};
return searchResult;
});
// Return an array of Search Results
return searchResults;
});
}
});
// Create Search widget using custom SearchSource
const searchWidget = new Search({
view: view,
sources: [customSearchSource],
includeDefaultSources: false
});
// Add the search widget to the top left corner of the view
view.ui.add(searchWidget, {
position: "top-right"
});
3d version of code sample above
There is no documented way to do this through the API, as far as I can tell. But by adding the esri-search--show-suggestions to the SearchWidget, the suggestions will reappear:
const searchWidget = new Search({
view: view,
sources: [customSearchSource],
includeDefaultSources: false,
//autoSelect: false,
goToOverride: function(view, { target, options }) {
view.goTo(target, options);
const widget = document.querySelector('.esri-search__container')
widget.className += ' esri-search--show-suggestions'
},
});
Working CodePen here
In this demo http://jsfiddle.net/mdz82oLn/ I have inserted videos (IDs) and images (png, jpeg, etc) which are also displayed by means of customized buttons. The demo works perfectly in the vision but reached the end of the last video it returns in loop when instead it should restart from the first video in the list, how to integrate this function?
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
const playerElement = document.querySelector('#player');
const imageElement = document.querySelector('#slide');
const videos = {
'RGpr3Y6Q-1M': 'http://nothingbutgeek.com/wp-content/uploads/2018/06/automata_16x9.png',
'btxdcqLOGuc': 'https://live.staticflickr.com/2400/2078946248_d063d5a563_b.jpg',
'CIx0a1vcYPc': 'https://i.ytimg.com/vi/CIx0a1vcYPc/maxresdefault.jpg',
};
const videoIds = Object.keys(videos);
function onYouTubeIframeAPIReady() {
function onPlayerReady({ target }) {
var playButton = document.getElementById("play-button");
playButton.addEventListener("click", function() {
target.playVideo();
});
var pauseButton = document.getElementById("pause-button");
pauseButton.addEventListener("click", function() {
target.pauseVideo();
});
var next = document.getElementById("next");
next.addEventListener("click", function() {
target.nextVideo();
});
var pre = document.getElementById("previous");
pre.addEventListener("click", function() {
target.previousVideo();
});
target.loadPlaylist({
playlist: videoIds
});
}
function onPlayerStateChange({ data, target }) {
switch(data) {
case YT.PlayerState.ENDED:
target.nextVideo();
break;
case YT.PlayerState.BUFFERING:
const playlist = target.getPlaylist();
const playlistIndex = target.getPlaylistIndex();
const currentId = playlist[playlistIndex];
const image = videos[currentId];
if (imageElement.src !== image) {
imageElement.src = image;
}
break;
}
}
const player = new YT.Player(playerElement, {
height: '405',
width: '720',
playerVars: {
controls: 1,
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
If I understand correctly you are stuck on last video and want to start the loop from 1 video:
In that case a change like this should work:
var next = document.getElementById("next");
next.addEventListener("click", function() {
target.nextVideo();
if(target.getPlaylistIndex() == videoIds.length -1){
target.loadPlaylist({
playlist: videoIds
});
}
});
Updated your Example
you can also update the switch case like this:
case YT.PlayerState.ENDED: {
if (target.getPlaylistIndex() == videoIds.length - 1) {
target.loadPlaylist({
playlist: videoIds
});
}
break;
}
I'm trying to upload a multipart form in nativescript and I'm using http-background. I keep getting the error Class constructor Observable cannot be invoked without 'new'. I've tried changing the compilerOptions target to es5 and es2017, but nothing changed.
Here's all my code from the component.
onSave(){
console.log("clicked")
this.proccessImageUpload(this.file);
}
public onSelectSingleTap() {
this.isSingleMode = true;
let context = imagepicker.create({
mode: "single"
});
this.startSelection(context);
}
private startSelection(context) {
let that = this;
context
.authorize()
.then(() => {
that.imageAssets = [];
that.imageSrc = null;
return context.present();
})
.then((selection) => {
console.log("Selection done: " + JSON.stringify(selection));
this.file = selection[0]._android;
that.imageSrc = that.isSingleMode && selection.length > 0 ? selection[0] : null;
// set the images to be loaded from the assets with optimal sizes (optimize memory usage)
selection.forEach(function (element) {
element.options.width = that.isSingleMode ? that.previewSize : that.thumbSize;
element.options.height = that.isSingleMode ? that.previewSize : that.thumbSize;
});
that.imageAssets = selection;
}).catch(function (e) {
console.log(e);
});
}
// proccess image function
proccessImageUpload(fileUri) {
var backgroundHttp = require("nativescript-background-http");
return new Promise((resolve, reject) => {
// body...
var request = {
url: 'http://192.168.0.2:4000/api/posts',
method: "POST",
headers: {
"Content-Type": "application/octet-stream",
"user_id": "<user_id>"
},
description: 'Uploading profile image..',
androidAutoDeleteAfterUpload: false,
androidNotificationTitle: 'Profile image'
}
var params = [
{ name: "title", value: "test" },
{ name: "content", value: "test" },
{ name: "fileToUpload", filename: fileUri, mimeType: "image/jpeg" }
];
var backgroundSession = backgroundHttp.session('image-upload');
var task = backgroundSession.uploadFile(fileUri, request);
task.on("progress", (e) => {
// console log data
console.log(`uploading... ${e.currentBytes} / ${e.totalBytes}`);
});
task.on("error", (e) => {
// console log data
console.log(`Error processing upload ${e.responseCode} code.`);
reject(`Error uploading image!`);
});
task.on("responded", (e) => {
// console log data
console.log(`received ${e.responseCode} code. Server sent: ${e.data}`);
// var uploaded_response = JSON.parse(e.data);
});
task.on("complete", (e) => {
// console log data
console.log(`upload complete!`);
console.log(`received ${e.responseCode} code`);
// console.log(e.data);
})
resolve(task);
});
}
I know the issue is coming from this line.
var task = backgroundSession.uploadFile(fileUri, request);
Any help would be greatly appreciated!
You use old version if nativescript-background-http plugin
You have to install latest version
tns plugin add #nativescript/background-http
I was able to get this working by installing tns version 6.
I had exactly the same problem. I got this from slack.com, compliments Chris Vietor
"tns plugin add nativescript-background-http" works with nativescript 6.
"tns plugin add #nativescript/background-http" works with nativescript 7.
I have a react-google-maps instance in my application which draws multiple location icons on google map. When there are more than one icons, sometimes, one icon, which have different location, gets stuck on another icon. The new icon is not clickable and gets removed automatically after giving a little nudge to the map (see image below)
IMO, the issue is with the google map's drawing multiple location icons.
Any idea, how can I fix this?
Here's how I am setting state when the component mounts
this.state = this.convertEntityStructureToComponentState(props.entities, props.hideInfoInitially, props.showDirections);
convertEntityStructureToComponentState() function looks like this:
convertEntityStructureToComponentState(entities, hideInfoInitially, showDirections=false) {
if (!entities || entities.length === 0) {
// send seattle longitude and latitude and set markers as null
const center = {
lat: 47.602743,
lng: -122.330626
};
return {
center: center,
markers: []
};
}
const markers = [];
let firstEntityReadings = null;
let destinationPosition = null;
let selectedEntityPosition = null;
let showPathLine = true;
for (let i = 0; i < entities.length; i++) {
if (entities[i].location) {
if (!firstEntityReadings) {
firstEntityReadings = {
lat: entities[i].location.lat,
lng: entities[i].location.lng
};
}
let showLocation = true;
if (entities[i].type === 'customer') {
destinationPosition = i;
} else {
if (this.isTimeInOnlineRange(entities[i].time)) {
selectedEntityPosition = i;
} else if (this.props.customerView) {
showLocation = false;
showPathLine = false;
}
}
if (showLocation) {
markers.push({
position: new google.maps.LatLng(entities[i].location.lat, entities[i].location.lng),
showInfo: false,
data: {
name: entities[i].name,
address: entities[i].address,
id: entities[i].id,
time: entities[i].time,
color: entities[i].type === 'customer' ? entities[i].color : '#ccc',
type: entities[i].type,
image_path: entities[i].image_path
}
});
}
}
}
//Optimize where we get previous location and don't call direction if it's the same
if (showDirections && destinationPosition != null && selectedEntityPosition != null && showPathLine) {
const DirectionsService = new google.maps.DirectionsService();
DirectionsService.route({
origin: new google.maps.LatLng(entities[selectedEntityPosition].location.lat, entities[selectedEntityPosition].location.lng),
destination: new google.maps.LatLng(entities[destinationPosition].location.lat, entities[destinationPosition].location.lng),
travelMode: google.maps.TravelMode.DRIVING,
}, (result, status) => {
if (status === google.maps.DirectionsStatus.OK) {
this.setState({
directions: result
});
}
});
} else {
this.setState({
directions: null
});
}
return {
center: firstEntityReadings,
markers: markers
};
}
Link to Github issue: https://github.com/tomchentw/react-google-maps/issues/805
Link to the gist of location map component: https://gist.github.com/arximughal/f91b7a922a4711e25ef82ed9ac6427b5
The issue was with the key and ref of the markers that I was drawing on the map. Generating a random ID for key fixed the issue properly.
I am working with ionic and i want to display map marker with store logo. I constructed a default marker and I have lots of store pics or logos which need to be placed within the marker show in above image. I have used cordova geolocation plugin for get current location of user.
Response array like this :
var markers = [{
storeName: "Dib Dab Extract",
profilePic: "img/dibdab.png",
address: "420 Mary Jane Way",
rating: "4",
reviews: "4379",
offer: "100 Free Coins with 1st Purchse",
lat: "53.896408",
long: "-105.991427"
}]
Custom Marker Icon :
var image = {
url: 'img/ic_map_pin_gray.png', // image is 512 x 512
scaledSize: new google.maps.Size(80, 80),
};
Marker set on map like this :
var markerPos = new google.maps.LatLng(record.lat, record.long);
// Add the markerto the map
var marker = new google.maps.Marker({
map: map,
animation: google.maps.Animation.DROP,
position: markerPos,
icon: image,
});
Issue is resolved using Custom Marker. I have done code like this and i get exact marker like i want in above question. So i posted this answer that help anyone who want custom marker like this. i have refer https://humaan.com/blog/custom-html-markers-google-maps/
// Map Initilize function
function initMap() {
var options = {
timeout: 10000,
enableHighAccuracy: true
};
$cordovaGeolocation.getCurrentPosition(options).then(function(position) {
var latLng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
var mapOptions = {
center: latLng,
zoom: 15,
disableDefaultUI: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map"), mapOptions);
//Wait until the map is loaded
//Load the markers
loadMarkers();
//});
}, function(error) {
console.log(error);
console.log("Could not get location");
//Load the markers
loadMarkers();
});
}
//load marker using rest api
function loadMarkers() {
CommonService.ShowLoader();
YOUR REST API SERVICE.then(function(res) {
angular.forEach(res, function(value, key) {
var record = value;
console.log(record);
var image = {
url: 'img/ic_map_pin_gray.png', // custom background image (marker pin)
scaledSize: new google.maps.Size(70, 70),
};
var markerPos = new google.maps.LatLng(record.lat, record.long);
//Add the markerto the map
var marker = new google.maps.Marker({
map: map,
animation: google.maps.Animation.DROP,
position: markerPos,
icon: image,
});
var img_src = record.profilePic;
var overlay = new CustomMarker(
markerPos,
map, {image: img_src}
);
});
}).catch(function(error, status, headers, config) {
console.log(error);
});
}
//CustomMarker function
function CustomMarker(latlng, map, args) {
this.latlng = latlng;
this.args = args;
this.setMap(map);
}
CustomMarker.prototype = new google.maps.OverlayView();
CustomMarker.prototype.draw = function() {
var self = this;
var div = this.div;
if (!div) {
div = this.div = document.createElement('img');
div.src = self.args.image;
div.className = 'marker';
div.style.position = 'absolute';
div.style.cursor = 'pointer';
div.style.width = '35px';
div.style.height = '35px';
div.style.borderRadius = '50%';
if (typeof(self.args.marker_id) !== 'undefined') {
div.dataset.marker_id = self.args.marker_id;
}
google.maps.event.addDomListener(div, "click", function(event) {
google.maps.event.trigger(self, "click");
});
var panes = this.getPanes();
panes.overlayImage.appendChild(div);
}
var point = this.getProjection().fromLatLngToDivPixel(this.latlng);
if (point) {
div.style.left = (point.x - 18) + 'px'; // set custom (i set it as i want to set in map )
div.style.top = (point.y - 56) + 'px'; //set custom (i set it as i want to set in map )
}
};
This worked for me.
marker = new MarkerWithLabel({
position: new google.maps.LatLng(item.latitude, item.longitude),
animation: google.maps.Animation.DROP,
labelContent: "My Job Location",
labelAnchor: new google.maps.Point(10, 38),
labelClass: "markLabelsJob", // the CSS class for the label
labelInBackground: false,
icon: 'img/active-job-pin.png',
map: map
});