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
Related
I have a script that on Form submit takes the data from the spreadsheet and creates a copy of a template and populates the google docs. I am trying to accomplish the same thing from google form to google slides.
First script I use for the google forms to google docs. The second script is my attempt of using the same principles and applying to google slides. My issue is I'm getting an error saying TypeError: values.forEach is not a function (line 109, file "Code") in relation to values.forEach(function(page). Any suggestions on how I could go about solving this?
Google Form to Google Sheets
function autoFillGoogleDocFromForm(e) {
var timestamp = e.values[0];
var address = e.values[1];
var image = e.values[2];
var price = e.values[3];
var summary = e.values[4];
var type = e.values[5];
var year_built = e.values[6];
var bed = e.values[7];
var bath = e.values[8];
var home_size = e.values[9];
var lot_size = e.values[10];
var occupancy = e.values[11];
var templateFile = DriveApp.getFileById("xxxxxxxx");
var templateResponseFolder = DriveApp.getFolderById("yyyyyyyyyy")
var copy = templateFile.makeCopy( address , templateResponseFolder);
var doc = DocumentApp.openById(copy.getId())
var body = doc.getBody();
body.replaceText("{{address}}", address);
body.replaceText("{{price}}", price);
body.replaceText("{{summary}}", summary);
body.replaceText("{{type}}", type);
body.replaceText("{{year_built}}", year_built);
body.replaceText("{{beds}}", bed);
body.replaceText("{{baths}}", bath);
body.replaceText("{{home_size}}", home_size);
body.replaceText("{{lot_size}}", lot_size);
body.replaceText("{{occupancy}}", occupancy);
doc.saveAndClose;
}
Google Form to Google Slides
function generateLandingPagesReport(){
var dataSpreadsheetUrl = "https://docs.google.com/spreadsheets/xxxxxxxxx/edit"
var Presentation_ID = "xxxxxxxxxxxxxx";
var ss = SpreadsheetApp.openByUrl(dataSpreadsheetUrl);
var deck = SlidesApp.openById(Presentation_ID);
var sheet = ss.getSheetByName('Sheet1');
var values = sheet.getRange('A1:J17').getValues;
var slides = deck.getSlides();
var templateSlide = slides[1];
var presLength = slides.length;
values.forEach(function(page){
values.forEach(function(page){
if(page[0]){
var landingPage = page[0];
var sessions = page[1];
var newSessions = page[2];
}
templateSlide.duplicate(); // duplicate the template page
/*slides = deck.getSlides(); // update the slides array for indexes and length*/
newSlide = slides[2]; // declare the new page to update
var shapes = (newSlide.getShapes());
shapes.forEach(function(shape){
shape.getText().replaceAllText('{{landing page}}', landingPage);
shape.getText().replaceAllText('{{sessions}}', sessions);
shape.getText().replaceAllText('{{new sessions}}',newSessions);
});
presLength = slides.length;
newSlide.move(presLength);
//end our condition statement
}); //close our loop of values
//remove template slide
templateSlide.remove();
});
}
You're missing the parenthesis when calling the getValue() method.
Change this:
var values = sheet.getRange('A1:J17').getValues;
To this:
var values = sheet.getRange('A1:J17').getValues();
Not exactly what I was looking for but this uses the first Row to identify the tag inside the Google slides template like {{title}} and replaces that with the value in the second row of the sheet
function createPresentation() {
var templateFile = DriveApp.getFileById("1YVEA4WtU1Kf6nZRgHpwnKBIR-V6rRN6s9zCdOQDkWNI");
var templateResponseFolder = DriveApp.getFolderById("1k7rcfXODij4o4arSULuKZUHbit1m_X64");
var copy = templateFile.makeCopy("New" , templateResponseFolder);
var Presentation = SlidesApp.openById(copy.getId());
var values = SpreadsheetApp.getActive().getDataRange().getValues();
values.forEach(function(row) {
var templateVariable = row[0];
var templateValue = row[1];
Presentation.replaceAllText(templateVariable, templateValue);
});
}
After you have copy the template page, you work on it and try to do replace.
However, change may be pending such that newSlide = slides[2]; give undefined.
You may need to try saveAndClose() before performing any actions.
templateSlide.duplicate(); // duplicate the template page
/*slides = deck.getSlides(); // update the slides array for indexes and length*/
/* flush the presentation */
deck.saveAndClose();
deck = SlidesApp.openById(Presentation_ID);
slides = deck.getSlides();
newSlide = slides[2]; // declare the new page to update
var shapes = (newSlide.getShapes());
shapes.forEach(function(shape){
shape.getText().replaceAllText('{{landing page}}', landingPage);
shape.getText().replaceAllText('{{sessions}}', sessions);
shape.getText().replaceAllText('{{new sessions}}',newSessions);
});
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>
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;
I'm working on a plug-in script for photoshop and I'm encountering a really weird problem, the closest person to have this problem is here : Why do class variables in Javascript disappear when trying to call them multiple times or assigning them to local variables?
So reading his solution I combed over my syntax and I can't find any issues that I didn't correct and try again. I'll include the full code in a bit but here is the gist of the problem, I'm declaring this object in global space by declaring it and it's members outside of functions:
prefs = new Object();
prefs.db_file = "";
prefs.bk_file = "";
prefs.text = new Object();
prefs.text.top = 0.6;
prefs.text.bottom = 0.9;
prefs.text.padding = 0.05;
prefs.text.size = 12;
prefs.text.shadow = true;
basic outline (pseudocode):
declare global variables
main() {
Dialogue()
do stuff with the variables
}
Dialogue() {
declare new window
accept user interaction
store in global variable
}
I've run through this several times, step by step in the extendscript debugger watching the variables, every time the variables exist and the values are correct, until they exit the Dialogue() function then the only variables that exist are prefs.text.shadow and prefs.text.size
everything I've tried, including removing the ".text." part has returned the same. I can't find if my syntax is wrong, if it is wrong than why don't all the prefs. variables disappear? and I'm fairly certain that all the variables are treated the same way.
Update 10-22-2013: To help rule out syntax issues I found JSlint and ran my code through it and went through and corrected the issues it presented. The only issues left are grouping 'var' selections. It changed my object declaration method, some code ordering, unnecessary ';'s standardizing my indents. The Result: The same. The same variables are dropped and the same output is returned.
Here is the full code:
#target photoshop
app.bringToFront();
prefs = new Object();
prefs.db_file = "";
prefs.bk_file = "";
prefs.text = new Object();
prefs.text.top = 0.6;
prefs.text.bottom = 0.9;
prefs.text.padding = 0.05;
prefs.text.size = 12;
prefs.text.shadow = true;
function main() {
Dialogue();
var db_file2 = new File(prefs.db_file);
db_file2.open('r');
var data = Array();
var str = "";
var data_str = "";
while(!db_file2.eof) {
str = db_file2.readln();
data.push(str.split(","));
data_str += str;
};
db_file2.close();
alert(data_str);
};
function Dialogue() {
var dlg = new Window ("dialog","Create New Slide Set");
dlg.orientation = "row";
dlg.alignChildren = "fill";
dlg.pref_group = dlg.add("group");
dlg.pref_group.orientation = "column";
dlg.pref_group.alignChildren = "fill";
dlg.pref_group.db_val = dlg.pref_group.add("edittext",undefined,prefs.db_file);
dlg.pref_group.db_find = dlg.pref_group.add("button",undefined,"select data file");
dlg.pref_group.db_find.onClick = function() {
selectedFile = File.openDialog("Please select CSV file.","CSV File:*.csv");
if(selectedFile != null) {
dlg.pref_group.db_val.text = decodeURI(selectedFile.fsName);
prefs.db_file = dlg.pref_group.db_val.text;
};
};
dlg.pref_group.db_val.onChange = function() {
prefs.db_file = dlg.pref_group.db_val.value;
alert("db_file has been changed!");
};
dlg.pref_group.bk_val = dlg.pref_group.add("edittext",undefined,prefs.bk_file);
dlg.pref_group.bk_find = dlg.pref_group.add("button",undefined,"select background image");
dlg.pref_group.bk_find.onClick = function() {
selectedFile = File.openDialog("Please select PNG file.","Image File:*.png");
if(selectedFile != null) {
dlg.pref_group.bk_val.text = decodeURI(selectedFile.fsName);
prefs.bk_file = dlg.pref_group.bk_val.text;
};
};
dlg.pref_group.bk_val.onChange = function() {
prefs.bk_file = dlg.pref_group.bk_val.value;
};
dlg.pref_group.tt_grp = dlg.pref_group.add("group");
dlg.pref_group.tt_grp.orientation = "row";
dlg.pref_group.tt_grp.alignChildren = "fill";
dlg.pref_group.tt_grp.tt = dlg.pref_group.tt_grp.add("statictext",undefined,"Text Top");
dlg.pref_group.tt_grp.tt_dsp = dlg.pref_group.tt_grp.add("edittext",undefined,prefs.text.top);
dlg.pref_group.tt_grp.tt_dsp.preferredsize = [100,200];
dlg.pref_group.tt_grp.tt_dsp.onChange = function() {
prefs.text.top = dlg.pref_group.tt_grp.tt_dsp.value;
};
dlg.pref_group.bt_grp = dlg.pref_group.add("group");
dlg.pref_group.bt_grp.orientation = "row";
dlg.pref_group.bt_grp.alignChildren = "fill";
dlg.pref_group.bt_grp.bt = dlg.pref_group.bt_grp.add("statictext",undefined,"Text bottom");
dlg.pref_group.bt_grp.bt_dsp = dlg.pref_group.bt_grp.add("edittext",undefined,prefs.text.bottom);
dlg.pref_group.bt_grp.bt_dsp.preferredsize = [100,200];
dlg.pref_group.bt_grp.bt_dsp.onChange = function() {
prefs.text.bottom = dlg.pref_group.bt_grp.bt_dsp.value;
};
dlg.pref_group.pd_grp = dlg.pref_group.add("group");
dlg.pref_group.pd_grp.orientation = "row";
dlg.pref_group.pd_grp.alignChildren = "fill";
dlg.pref_group.pd_grp.pd = dlg.pref_group.pd_grp.add("statictext",undefined,"Padding");
dlg.pref_group.pd_grp.pd_dsp = dlg.pref_group.pd_grp.add("edittext",undefined,prefs.text.padding);
dlg.pref_group.pd_grp.pd_dsp.preferredsize = [100,200];
dlg.pref_group.pd_grp.pd_dsp.onChange = function() {
prefs.text.padding = dlg.pref_group.pd_grp.pd_dsp.value;
};
dlg.pref_group.sd_grp = dlg.pref_group.add("group");
dlg.pref_group.sd_grp.orientation = "row";
dlg.pref_group.sd_grp.alignChildren = "fill";
dlg.pref_group.sd_grp.sd = dlg.pref_group.sd_grp.add("statictext",undefined,"Shadow");
dlg.pref_group.sd_grp.sd_dsp = dlg.pref_group.sd_grp.add("checkbox",undefined,"");
dlg.pref_group.sd_grp.sd_dsp.value = prefs.text.shadow;
dlg.pref_group.sd_grp.sd_dsp.onChange = function() {
prefs.text.shadow = dlg.pref_group.sd_grp.sd_dsp.value;
};
dlg.ok_group = dlg.add('group');
dlg.ok_group.orientation = "column";
dlg.ok_group.ok_btn = dlg.ok_group.add("button",undefined,"ok");
dlg.ok_group.ok_btn.onClick = function() {
prefs.text.shadow = dlg.pref_group.sd_grp.sd_dsp.value;
prefs.text.padding = dlg.pref_group.pd_grp.pd_dsp.value;
prefs.text.bottom = dlg.pref_group.bt_grp.bt_dsp.value;
prefs.text.top = dlg.pref_group.tt_grp.tt_dsp.value;
prefs.bk_file = dlg.pref_group.bk_val.value;
prefs.db_file = dlg.pref_group.db_val.value;
dlg.close(0);
};
dlg.center();
dlg.show();
};
main();
it was so simple...
'edittext' boxes don't have .value properties they have .text properties, trying to access .value returned a null and destroyed the variable.
my research took me into a lot of areas, syntax conventions, JSlint, object definitions, ironically looking into a different problem (onChange functions aren't being called) made me realize that the only variables that weren't being disregarded were the shadow checkbox, and the font size parameter, but the font size parameter wasn't being edited at all at this point, and the shadow was the only thing being defined by a checkbox. Lesson learned: when something is partially working compare the similarities of the working part
I'm stuck with no clues how to copy image to clipboard.
My code looks like this:
var image = "data:image/png;base64,..."
var io = Components.classes["#mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
var channel = io.newChannel(image, null, null);
var input = channel.open();
var trans = Components.classes["#mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
trans.addDataFlavor("image/png");
trans.setTransferData("image/png", input, input.available());
var clipid = Components.interfaces.nsIClipboard;
var clip = Components.classes["#mozilla.org/widget/clipboard;1"].getService(clipid);
clip.setData(trans, null, clipid.kGlobalClipboard);
As Neil already noted in the newsgroup, the data expected for an image is an nsIContainer instance rather than a stream. I couldn't find any examples of doing that on the web so I modified your code:
var image = "data:image/png;base64,...";
var io = Components.classes["#mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
var channel = io.newChannel(image, null, null);
var input = channel.open();
var imgTools = Components.classes["#mozilla.org/image/tools;1"].getService(Components.interfaces.imgITools);
var container = {};
imgTools.decodeImageData(input, channel.contentType, container);
var trans = Components.classes["#mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
trans.addDataFlavor("image/png");
trans.setTransferData("image/png", container.value, -1);
var clipid = Components.interfaces.nsIClipboard;
var clip = Components.classes["#mozilla.org/widget/clipboard;1"].getService(clipid);
clip.setData(trans, null, clipid.kGlobalClipboard);
For me this copies the image to clipboard correctly.