Leaflet.Draw saving data with GeoJson - javascript

map.addControl(new L.Control.Draw({
draw: {
polygon: false,
polyline: false,
rectangle: false,
circle: false
},
edit: {featureGroup: drawnItems}
}));
map.on('draw:created', function(e) {
var type = e.layerType;
var layer = e.layer;
var idIW = L.popup();
var content = '<span><b>Title</b></span><br/><input id="salrepnu" type="text"/><br/><br/><span><b>Report<b/></span><br/><textarea id="salrep" cols="25" rows="5"></textarea><br/><br/><input type="button" id="okBtn" value="Save" onclick="saveIdIW()"/>';
idIW.setContent(content);
idIW.setLatLng(layer.getLatLng());
idIW.openOn(map);
drawnItems.addLayer(layer)
});
function saveIdIW() {
var sName = $('#salrepnu').val();
var salRep = $('#salrep').val();
var drawings = drawnItems.getLayers(); //drawnItems is a container for the drawn objects
drawings[drawings.length - 1].title = sName;
drawings[drawings.length - 1].content = salRep;
map.closePopup();
};
//Export
document.getElementById('export').onclick = function(e) {
// Extract GeoJson from featureGroup
var data = drawnItems.toGeoJSON();
// Stringify the GeoJson
var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data));
// Create export
document.getElementById('export').setAttribute('href', 'data:' + convertedData);
document.getElementById('export').setAttribute('download', 'drawnItems.geojson');
}
I added leaflet.draw.js and leaflet.draw.css and I can set up a map from an external geoJson file; but I can't for the life of me figure out how to save input html to a geoJson feature as the featureGroup drawnItems will export the long and lat but not the html features.
I want the featureGroup markers to append to a geoJson file that will then show up on a live map. Any help is appreciated
map.on('draw:created', function(e) {
var type = e.layerType;
var layer = e.layer;
var feature = layer.feature = layer.feature || {}; // Intialize layer.feature
feature.type = feature.type || "Feature"; // Intialize fueature.type
var props = feature.properties = feature.properties || {}; // Intialize feature.properties
if (type === 'marker'){
props.repnumb = prompt("Sales Report No. ");
props.sales = prompt("Sales");
var popContent = "<p><b>SALUTE Report No. " +
props.repnumb + "</b></br>" +
"<b>Sales: " + props.sales + "</b></p>";
layer.bindPopup(popContent);
}
drawnItems.addLayer(layer)
});
I figured out how to create clean feature inputs, but the prompt method seems lacking in the format department. There is a popup that asks a question, but at least the question comes up on the marker now after it is set.

From save from leaflet draw which contains a Full demo.
...
<body>
<a href='#' id='export'>Export Features</a>
<script>
document.getElementById('export').onclick = function(e) {
// Extract GeoJson from featureGroup
var data = featureGroup.toGeoJSON();
// Stringify the GeoJson
var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data));
// Create export
document.getElementById('export').setAttribute('href', 'data:' + convertedData);
document.getElementById('export').setAttribute('download','data.geojson');
}
</script>
</body>

Related

Leaflet geoJSON doesn't stringify TurfCircle

I have fixed an issue with the drawing circles by the Leaflet draw plugin, where the Turf library has been provided.
Everything works fine, apart from the data, which I passed earlier by the prompt function. They come out only in the point created as the circle by standard code. Unfortunately, it is nothing for TurfCircle the same as NewTurfBuffer.
My code (used in Python folium) looks as follows:
map.on(L.Draw.Event.CREATED, function(e) {
var layer = e.layer,
type = e.layerType;
feature = layer.feature = layer.feature || {}; // Initialize feature
let x = 1
var title = prompt("Please provide the name", "default");
var value = prompt("Please provide the value", "undefined");
var id = x++;
feature.type = feature.type || "Feature"; // Initialize feature type
if (type === 'circle') {
var theCenterPt = layer.getLatLng();
var center = [theCenterPt.lng,theCenterPt.lat];
console.log(center);
console.log(title);
var theRadius = layer.getRadius();
var turfCircle;
var options = {steps: 256, units: 'meters'};
var turfCirle = turf.circle(center, theRadius, options);
var NewTurfCircle = new L.GeoJSON(turfCircle)
drawnItems.addLayer(NewTurfCircle);
var thepoint = turf.point(center);
var buffered = turf.buffer(thepoint, theRadius, {units: 'meters'});
var NewTurfBuffer = new L.GeoJSON(buffered)
drawnItems.addLayer(NewTurfBuffer);
}
var props = feature.properties = feature.properties || {}; // Initialize feature properties
props.Id = id;
props.Title = title;
props.Value = value;
var coords = JSON.stringify(layer.toGeoJSON(), NewTurfBuffer);
{%- if this.show_geometry_on_click %}
layer.on('click', function() {
alert(coords);
console.log(coords);
});
{%- endif %}
drawnItems.addLayer(layer);
});
I still get empty properties for my FeatureCollection
I think the issue can be similar to this one:
Why doesn't JSON.stringify display object properties that are functions?
https://gis.stackexchange.com/questions/332908/overlay-with-the-feature-collection-properties
but it looks like I am wrong in placing my properties inside of the FeatureCollection
https://gis.stackexchange.com/questions/25279/is-it-valid-to-have-a-properties-element-in-an-geojson-featurecollection
anyway, I am looking for a solution that will allow me to pass the data to these properties boxes.
UPDATE II:
I tried
var buffered = turf.buffer(thepoint, theRadius, {units: 'meters'});
buffered.push(layer.feature);
var NewTurfBuffer = new L.GeoJSON(buffered)
drawnItems.addLayer(NewTurfBuffer);
but an error occurs:
buffered.push is not a function
Hint taken from here:
https://gis.stackexchange.com/questions/285352/how-to-get-the-exact-circle-that-user-has-drawn-using-leaflet-draw-circle

amcharts4 getting map elements to link to URL using polygon property

The following (while call core.js, maps.js, animated.js and a contextual countryLow.js file renders a map with polygons of regions (or sub-administrative districts):
var chart = am4core.create("chartdiv", am4maps.MapChart);
chart.geodata = am4geodata_franceLow;
chart.projection = new am4maps.projections.Miller();
var polygonSeries = chart.series.push(new am4maps.MapPolygonSeries());
polygonSeries.useGeodata = true;
polygonSeries.applyOnClones = true;
polygonSeries.fill = am4core.color("#a791b4");
polygonSeries.fillOpacity = 0.8;
polygonSeries.strokeOpacity = 0.3;
var regionTemplate = polygonSeries.mapPolygons.template;
regionTemplate.tooltipText = "{name}";
regionTemplate.properties.fillOpacity = 0.8;
regionTemplate.propertyFields.fill = "color";
regionTemplate.propertyFields.url = "url";
regionTemplate.columns.template.url = "http://localhost:3000/go/cities?region_id={properties.id()}"
While the tooltip is being revealed, how can one get the polygon to be clickable while passing the polygon's ID value as a parameter to the URL?
Just write zeroin code in Javascript instead of typescript and you will not have the error ;
regionTemplate.url = "http://www.amcharts.com/";
regionTemplate.adapter.add("url", function(url, target) { return url + "?id=" + target.dataItem.dataContext.id; }):
You can use placeholders in URLs. E.g.:
regionTemplate.url = "http://localhost:3000/go/cities?region_id={id.urlEncode()}"
Demo:
https://codepen.io/team/amcharts/pen/30dc8cb2bcdef6a2d5f11d41db1e58a1
You can use adapter to modify original url, like:
regionTemplate.url = "http://www.amcharts.com/";
regionTemplate.adapter.add("url", (url, target)=>{
return url + "?id=" + target.dataItem.dataContext.id;
})

How to get all the pins/markers in on click of a markercluster in google maps?

I am using google maps api to create a store locator with clusters and I am referring the marker cluster api.
I wanted to get the list of stores with in a markercluster rather than returning marker cluster with pins/markers. Please find the below code -
google.maps.event.addListener(mapsCore.mapsVar.markerCluster, 'clusterclick', function(cluster) {
var content = "";
// Convert lat/long from cluster object to a usable MVCObject
var info = new google.maps.MVCObject;
info.set('position', cluster.center_);
//----
//Get markers
console.log(cluster.getSize());
var markers = cluster.getMarkers();
var x = {};
$(mapsCore.mapsVar.totalResults.Result).each(function(k, v) {
$(markers).each(function(km, vm) {
if (parseFloat(v.LAT) == parseFloat(markers[km].position.lat()) && parseFloat(v.LON) == parseFloat(markers[km].position.lng())) {
// locArr[k] = { lat: parseFloat(v.CounterLatitude), lng: parseFloat(v.CounterLongitude) };
x.Counter_ID = v.Counter_ID;
x.Counter_Name = v.Counter_Name;
x.Counter_Zip_code = v.Counter_Zip_code;
x.Address_1 = v.Address_1;
x.Address_2 = v.Address_2;
x.Province = v.Province;
x.City = v.City;
x.Area = v.Area;
x.SubArea = v.SubArea;
x.Counter_Tel = v.Counter_Tel;
x.Counter_Email = v.Counter_Email;
x.Open_Time = v.Open_Time;
x.Close_Time = v.Close_Time;
x.LAT = v.LAT;
x.LON = v.LON;
x.MR_FLG = v.MR_FLG;
mapsCore.mapsVar.clusterDetail.Results.push(x);
x = {};
}
});
});
});
As a workaround you can set a custom image to an transparent png and text size to 0, that way it'll be invisible on the map.
cluster.setStyles({
url: your_path/transparent.png,
height: 20,
width: 20,
textSize: 0
});
Alternatively you can try and see if setting the image height and width to 0 works.
All,
thanks for your help for formatting my code and comments any way I found the solution for it. I will attach the spinet of code below
google.maps.event.addListener(mapsCore.mapsVar.markerCluster, 'clusterclick', function(cluster) {
var content = '';
// Convert lat/long from cluster object to a usable MVCObject
var info = new google.maps.MVCObject;
info.set('position', cluster.center_);
//----
//Get markers
console.log(cluster.getSize());
var markers = cluster.getMarkers();
var x = {};
mapsCore.mapsVar.clusterDetail.Counters.length = 0;
$(mapsCore.mapsVar.totalResults.Counters).each(function(k, v) {
$(markers).each(function(km, vm) {
console.log(parseFloat(v.CounterLatitude) == parseFloat(vm.position.lat()) && parseFloat(v.CounterLongitude) == parseFloat(vm.position.lng()));
if (parseFloat(v.CounterLatitude) == parseFloat(vm.position.lat())) {
// locArr[k] = { lat: parseFloat(v.CounterLatitude), lng: parseFloat(v.CounterLongitude) };
x.CounterCode = v.CounterCode;
x.CounterName = v.CounterName;
x.CounterZipCode = v.CounterZipCode;
x.AddressLine1 = v.AddressLine1;
x.AddressLine2 = v.AddressLine2;
x.Province = v.Province;
x.City = v.City;
x.Area = v.Area;
x.SubArea = v.SubArea;
x.CounterPhoneNumber = v.CounterPhoneNumber;
x.CounterEmailAddress = v.CounterEmailAddress;
x.CounterOpenTime = v.CounterOpenTime;
x.CounterCloseTime = v.CounterCloseTime;
x.CounterLatitude = v.CounterLatitude;
x.CounterLongitude = v.CounterLongitude;
x.IsMagicRingAvailable = v.IsMagicRingAvailable;
mapsCore.mapsVar.clusterDetail.Counters.push(x);
x = {};
}
});
});
console.log(mapsCore.mapsVar.clusterDetail);
var template = $.templates("#mapslist");
var output = template.render(mapsCore.mapsVar.clusterDetail);
$(".store-list-section").html(output);
});
Always need to reset the array of object like -
mapsCore.mapsVar.clusterDetail.Counters.length = 0;

iterate arrays with forEach Loop

in this project there are 3 files, index.html, helper.js and resumeBuilder.js. The last one is the file I work with all the time.
My problem in this project is that I can't figure how to make images array,which is inside the projects array to display in my Resume, and the same for the onLineCourses array which is inside the schools array. This online school needs to make all arrays with
forEach loop. please if someone can help to write the code I have to write to make it display, I am searching for a week and can't figure it out!
resumeBuilder.js
var projects = {
"projects" : [
{
"title":"",
"location":"",
"dates":"",
"description":"",
},
{
"title":"",
"location":"",
"dates":"",
"description":"",
>
> "images":["", ""]
}
],
};
//projects function
projects.display = function(){
$.each(projects.projects, function(i){
$("#projects").append(HTMLprojectStart);
var myProjects = projects.projects[i];
var formattedTitle = HTMLprojectTitle.replace("%data%", myProjects.title);
$(".project-entry:last").append(formattedTitle);
var formattedDates = HTMLprojectDates.replace("%data%", myProjects.dates);
$(".project-entry:last").append(formattedDates);
var formattedDescription = HTMLprojectDescription.replace("%data%", myProjects.description);
$(".project-entry:last").append(formattedDescription);
> //image array here!
> var formattedImage = HTMLprojectImage.replace("%data%",projects.images);
> $("#projects").append(HTMLprojectStart);
> $(".project-entry:last").append(formattedImage);
});
};
projects.display();
> var education = {
"schools": [
{
"name" : "",
"location" : "",
"degree":",
"majors":["","",""],
"dates" : "2",
"url" : ""
},
{
"name" : "",
"location" :"",
"degree":"",
"majors":[""],
"dates" : "",
"url" : ""
}
],
//create onLine Courses
> "onlineCourses" : [
> {
> "title" : "",
> "school" : "",
> "dates" : "",
> "url" : ""
> } ] };
//education function
education.display = function(){
$.each(education.schools, function(i) {
var mySchools = education.schools[i];
$("#education").append(HTMLschoolStart);
var formattedName = HTMLschoolName.replace("%data%",mySchools.name);
var formattedDegree = HTMLschoolDegree.replace("%data%",mySchools.degree);
var formattedNameDegree = formattedName + formattedDegree;
$(".education-entry:last").append(formattedNameDegree);
var formattedDates = HTMLschoolDates.replace("%data%",mySchools.dates);
$(".education-entry:last").append(formattedDates);
var formattedLocation = HTMLschoolLocation.replace("%data%",mySchools.location);
$(".education-entry:last").append(formattedLocation);
var formattedMajor = HTMLschoolMajor.replace("%data%",mySchools.majors);
$(".education-entry:last").append(formattedMajor);
});
//onLine courses here
> $("#education").append(HTMLonlineClasses);
> $("#education").append(HTMLschoolStart); var courses =
> education.onlineCourses; var formattedTitle =
> HTMLonlineTitle.replace("%data%", courses.title); var
> formattedSchool = HTMLonlineSchool.replace("%data%",courses.name);
> var formattedDates = HTMLonlineDates.replace("%data%", courses.dates);
> var formattedOnline = formattedTitle + formattedSchool +
> formattedDates;
> $(".education-entry:last").append(formattedOnline);
>
> };
>
> education.display();
helper.js
> /*
This file contains all of the code running in the background that makes resumeBuilder.js possible. We call these helper functions because they support your code in this course.
Don't worry, you'll learn what's going on in this file throughout the course. You won't need to make any changes to it until you start experimenting with inserting a Google Map in Problem Set 3.
/*
These are HTML strings. As part of the course, you'll be using JavaScript functions
replace the %data% placeholder text you see in them.
*/
var HTMLheaderName = '<h1 id="name">%data%</h1>';
var HTMLheaderRole = '<span>%data%</span><hr>';
var HTMLcontactGeneric = '<li class="flex-item"><span class="orange-text">%contact%</span><span class="white-text">%data%</span></li>';
var HTMLmobile = '<li class="flex-item"><span class="orange-text">mobile</span><span class="white-text">%data%</span></li>';
var HTMLemail = '<li class="flex-item"><span class="orange-text">email</span><span class="white-text">%data%</span></li>';
var HTMLtwitter = '<li class="flex-item"><span class="orange-text">twitter</span><span class="white-text">%data%</span></li>';
var HTMLgithub = '<li class="flex-item"><span class="orange-text">github</span><span class="white-text">%data%</span></li>';
var HTMLblog = '<li class="flex-item"><span class="orange-text">blog</span><span class="white-text">%data%</span></li>';
var HTMLlocation = '<li class="flex-item"><span class="orange-text">location</span><span class="white-text">%data%</span></li>';
var HTMLbioPic = '<img src="%data%" class="biopic">';
var HTMLwelcomeMsg = '<span class="welcome-message">%data%</span>';
var HTMLskillsStart = '<h3 id="skills-h3">Skills at a Glance:</h3><ul id="skills" class="flex-column"></ul>';
var HTMLskills = '<li class="flex-item"><span class="white-text">%data%</span></li>';
var HTMLworkStart = '<div class="work-entry"></div>';
var HTMLworkEmployer = '<a href="#">%data%';
var HTMLworkTitle = ' - %data%</a>';
var HTMLworkDates = '<div class="date-text">%data%</div>';
var HTMLworkLocation = '<div class="location-text">%data%</div>';
var HTMLworkDescription = '<p><br>%data%</p>';
var HTMLprojectStart = '<div class="project-entry"></div>';
var HTMLprojectTitle = '%data%';
var HTMLprojectDates = '<div class="date-text">%data%</div>';
var HTMLprojectDescription = '<p><br>%data%</p>';
var HTMLprojectImage = '<img src="%data%">';
var HTMLschoolStart = '<div class="education-entry"></div>';
var HTMLschoolName = '<a href="#">%data%';
var HTMLschoolDegree = ' -- %data%</a>';
var HTMLschoolDates = '<div class="date-text">%data%</div>';
var HTMLschoolLocation = '<div class="location-text">%data%</div>';
var HTMLschoolMajor = '<em><br>Major: %data%</em>';
var HTMLonlineClasses = '<h3>Online Classes</h3>';
var HTMLonlineTitle = '<a href="#">%data%';
var HTMLonlineSchool = ' - %data%</a>';
var HTMLonlineDates = '<div class="date-text">%data%</div>';
var HTMLonlineURL = '<br>%data%';
var internationalizeButton = '<button>Internationalize</button>';
var googleMap = '<div id="map"></div>';
$(document).ready(function() {
$('button').click(function() {
var $name = $('#name');
var iName = inName($name.text()) || function(){};
$name.html(iName);
});
});
/*
The next few lines about clicks are for the Collecting Click Locations quiz in the lesson Flow Control from JavaScript Basics.
*/
var clickLocations = [];
function logClicks(x,y) {
clickLocations.push(
{
x: x,
y: y
}
);
console.log('x location: ' + x + '; y location: ' + y);
}
$(document).click(function(loc) {
// your code goes here!
});
var map; // declares a global map variable
/*
Start here! initializeMap() is called when page is loaded.
*/
function initializeMap() {
var locations;
var mapOptions = {
disableDefaultUI: true
};
/*
For the map to be displayed, the googleMap var must be
appended to #mapDiv in resumeBuilder.js.
*/
map = new google.maps.Map(document.querySelector('#map'), mapOptions);
/*
locationFinder() returns an array of every location string from the JSONs
written for bio, education, and work.
*/
function locationFinder() {
// initializes an empty array
var locations = [];
// adds the single location property from bio to the locations array
locations.push(bio.contacts.location);
// iterates through school locations and appends each location to
// the locations array. Note that forEach is used for array iteration
// as described in the Udacity FEND Style Guide:
// https://udacity.github.io/frontend-nanodegree-styleguide/javascript.html#for-in-loop
education.schools.forEach(function(school){
locations.push(school.location);
});
// iterates through work locations and appends each location to
// the locations array. Note that forEach is used for array iteration
// as described in the Udacity FEND Style Guide:
// https://udacity.github.io/frontend-nanodegree-styleguide/javascript.html#for-in-loop
work.jobs.forEach(function(job){
locations.push(job.location);
});
return locations;
}
/*
createMapMarker(placeData) reads Google Places search results to create map pins.
placeData is the object returned from search results containing information
about a single location.
*/
function createMapMarker(placeData) {
// The next lines save location data from the search result object to local variables
var lat = placeData.geometry.location.lat(); // latitude from the place service
var lon = placeData.geometry.location.lng(); // longitude from the place service
var name = placeData.formatted_address; // name of the place from the place service
var bounds = window.mapBounds; // current boundaries of the map window
// marker is an object with additional data about the pin for a single location
var marker = new google.maps.Marker({
map: map,
position: placeData.geometry.location,
title: name
});
// infoWindows are the little helper windows that open when you click
// or hover over a pin on a map. They usually contain more information
// about a location.
var infoWindow = new google.maps.InfoWindow({
content: name
});
// hmmmm, I wonder what this is about...
google.maps.event.addListener(marker, 'click', function() {
// your code goes here!
//quiz 4 lesson 6
infowindow.open(map, marker);
});
// this is where the pin actually gets added to the map.
// bounds.extend() takes in a map location object
bounds.extend(new google.maps.LatLng(lat, lon));
// fit the map to the new marker
map.fitBounds(bounds);
// center the map
map.setCenter(bounds.getCenter());
}
/*
callback(results, status) makes sure the search returned results for a location.
If so, it creates a new map marker for that location.
*/
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
createMapMarker(results[0]);
}
}
/*
pinPoster(locations) takes in the array of locations created by locationFinder()
and fires off Google place searches for each location
*/
function pinPoster(locations) {
// creates a Google place search service object. PlacesService does the work of
// actually searching for location data.
var service = new google.maps.places.PlacesService(map);
// Iterates through the array of locations, creates a search object for each location
locations.forEach(function(place){
// the search request object
var request = {
query: place
};
// Actually searches the Google Maps API for location data and runs the callback
// function with the search results after each search.
service.textSearch(request, callback);
});
}
// Sets the boundaries of the map based on pin locations
window.mapBounds = new google.maps.LatLngBounds();
// locations is an array of location strings returned from locationFinder()
locations = locationFinder();
// pinPoster(locations) creates pins on the map for each location in
// the locations array
pinPoster(locations);
}
/*
Uncomment the code below when you're ready to implement a Google Map!
*/
// Calls the initializeMap() function when the page loads
window.addEventListener('load', initializeMap);
// Vanilla JS way to listen for resizing of the window
// and adjust map bounds
window.addEventListener('resize', function(e) {
//Make sure the map bounds get updated on page resize
map.fitBounds(mapBounds);
});

Turning specific photoshop layers off as data is read from csv file

I am new to javascript and am trying to write a script for use in photoshop that reads data from a csv file. The photoshop file has a variety of text layers that are fed data from the csv. I am having trouble turning off an image layer for every line of csv completed. Any ideas on how I could write this?
Here is the code so far:
var data = [];
var dataFile = new File(app.activeDocument.path + '/data.csv');
dataFile.open('r');
dataFile.readln(); // Skip first line
while (!dataFile.eof) {
var dataFileLine = dataFile.readln();
var dataFilePieces = dataFileLine.split(',');
data.push({
art: dataFilePieces[0],
tileNumber: dataFilePieces[0],
tileCommon: dataFilePieces[1],
tileSpecies: dataFilePieces[2],
tileDescription: dataFilePieces[3],
tileStatus: dataFilePieces[4],
});
}
dataFile.close();
for (var tileIndex = 0; tileIndex < data.length; tileIndex++) {
var tileData = data[tileIndex];
//update number
app.activeDocument.artLayers.getByName('Tile number').textItem.contents = tileData.tileNumber;
//update common name
app.activeDocument.artLayers.getByName('Common name').textItem.contents = tileData.tileCommon;
//update species name
app.activeDocument.artLayers.getByName('Species name').textItem.contents = tileData.tileSpecies;
//update description
app.activeDocument.artLayers.getByName('Description').textItem.contents = tileData.tileDescription;
file = new File(app.activeDocument.path + '/' + tileData.tileCommon + '.png');
opts = new ExportOptionsSaveForWeb();
opts.format = SaveDocumentType.PNG;
opts.PNG8 = false;
opts.quality = 100;
app.activeDocument.exportDocument(file, ExportType.SAVEFORWEB, opts);
}
confirm("All done!");

Categories

Resources