Scan folder for .shp extension and add to leaflet map - javascript

I am trying to scan a folder for all .shp files and add them to my leaflet map as a layer. The problem I'm having is that AJAX doesn't appear to be able to scan a folder, rather it is only capable of searching for specific files. I need it to be able to scan the folder because the .shp files will be overwritten periodically with new file names and I don't know how many files will be there at a given time. If there are no files in the folder, I need a popup to notify that maps are unavailable (this works in the current website). The code for this section is provided below. I've tried using PHP, but I can't figure out how to incorporate that with JavaScript.
I'm not a programmer, but I have stumbled through developing our website on my own. You can view it here: http://hsvfms.azurewebsites.net/map.html
If I haven't provided enough information or have given this information out of context, please let me know. Also, check out the website and let me know what you think.
var noMaps = L.control ();
var profile01 = new L.LayerGroup();
var profile02 = new L.LayerGroup();
$.ajax({
type:"GET",
url:"Aldridge_Unet/",
success: function(data) {
$(data).find("a:contains(.shp)").each(function(){
var mapList=[];
var profile0 = new L.Shapefile(mapList[0],{color:'DarkCyan',fillOpacity:'0.5', opacity:'5', weight:'1'}).addTo(profile01);
var profile1 = new L.Shapefile(mapList[1],{color:'DarkCyan',fillOpacity:'0.5', opacity:'5', weight:'1'}).addTo(profile02);
})
},
error: function (xhr, status, error) {
if(xhr.status==404){
noMaps = L.control ({position:'bottomleft'});
noMaps.onAdd = function(map) { var div = L.DomUtil.create('div', 'info legend');
div.innerHTML += '<img src="Images/map_not_available.png" alt="legend" style="width:275px;height:75px;background-color:white">';
return div;};
}
}
});
var overlays = [{groupName:"Inundation Boundaries", expanded:false, layers:{"Max Value":profile01}},];

Cannot be done. JavaScript code cannot access the filesystem of the computer the browser is running in (let alone watch a path for changes).
AJAX (and fetch and similar techniques) are just ways of fetching information from another computer (the web server). If your question really is "when something changes in the web server, how can I update the clients?" then the answer is probably WebSockets, socket.io, and similar techniques.

Related

Display generated Google Map image on a web page

I am using Google Apps Script to create a page, on which I would like to embed maps. The maps themselves would be static, but the map could be different depending on other parameters (it’s a genealogy page, and I’d like to display a map of birth and death locations, and maybe some other map points, based on a selected individual).
Using Google’s Maps service, I know that I can create a map, with a couple points built in.
Function getMapImage() {
var map = Maps.newStaticMap()
.setSize(600,400)
.addMarker('Chicago, Illinois') // markers would be based on a passed parm; this is just test data
.addMarker('Pocatello, Idaho');
// *** This is where I am looking for some guidance
return(); // obviously, I'm not returning a blank for real
}
Within the map class, there are a number of things I can do with it at this point.
I could create a URL, and pass that back. That appears to require an API account, which at this point, I do not have (and ideally, would like to avoid, but maybe I’ll have to do that). It also appears that I will run into CORB issues with that, which I think is beyond my knowledge (so if that’s the solution, I’ll be back for more guidance).
I could create a blob as an image, and pass that back to my page. I have tried this using a few different examples I have found while researching this.
Server Side
function getMapImage() {
var map = Maps.newStaticMap()
.setSize(600,400)
.addMarker('Chicago, Illinois')
.addMarker('Pocatello, Idaho');
var mapImage = map.getAs("image/png");
// OR
// var mapImage = map.getBlob();
return(mapImage);
}
Page side
<div id=”mapDiv”></div>
<script>
$(function() {
google.script.run.withSuccessHandler(displayMap).getMapImage();
}
function displayMap(mapImage) {
var binaryData = [];
binaryData.push(mapImage);
var mapURL = window.URL.createObjectURL(new Blob(binaryData, {type: "image/png"}))
var mapIMG = "<img src=\'" + mapURL + "\'>"
$('#mapDiv').html(mapIMG);
}
</script>
The page calls getMapImage() on the server, and the return data is sent as a parm to displayMap().
var mapIMG ends up resolving to <img src='blob:https://n-a4slffdg23u3pai7jxk7xfeg4t7dfweecjbruoa-0lu-script.googleusercontent.com/51b3d383-0eef-41c1-9a50-3397cbe83e0d'> This version doesn't create any errors in the console, which other options I tried did. But on the page, I'm just getting the standard 16x16 image not found icon.
I’ve tried a few other things based on what I’ve come across in researching this, but don’t want to litter this post with all sorts of different code snippets. I’ve tried a lot of things, but clearly not the right thing yet.
What’s the best / correct (dare I ask, simplest) way to build a map with Google’s Map class, and then serve it to a web page?
EDIT: I added a little more detail on how the server and page interact, in response to Tanaike's question.
Modification points:
I think that in your script, Blob is returned from Google Apps Script to Javascript using google.script.run. Unfortunately, in the current stage, Blob data cannot be directly sent from from Google Apps Script to Javascript. I think that this might be the reason of your issue.
In this case, I would like to propose to directly create the data URL at the Google Apps Script side. When your script is modified, it becomes as follows.
Modified script:
Google Apps Script side:
function getMapImage() {
var map = Maps.newStaticMap()
.setSize(600, 400)
.addMarker('Chicago, Illinois')
.addMarker('Pocatello, Idaho');
var blob = map.getAs("image/png"); // or map.getBlob()
var dataUrl = `data:image/png;base64,${Utilities.base64Encode(blob.getBytes())}`;
return dataUrl;
}
Javascript side:
$(function() {
google.script.run.withSuccessHandler(displayMap).getMapImage();
});
function displayMap(mapURL) {
var mapIMG = "<img src=\'" + mapURL + "\'>"
$('#mapDiv').html(mapIMG);
}
In your Javascript side, $(function() {google.script.run.withSuccessHandler(displayMap).getMapImage();} is not enclosed by ). Please be careful this.
Note:
In my environment, when I saw <div id=”mapDiv”></div>, this double quote ” couldn't be used. So if in your environment, an error occurs by <div id=”mapDiv”></div>, please modify ” to " like <div id="mapDiv"></div>.
Reference:
base64Encode(data)

Open a directory of images into separate layers using Adobe extension

I am developing an Adobe extension, from within the extension I want to load a directory of images into separate layers within a document. I am completely impartial to how this is done - so if there is a better approach, please share it with me. My current working method involves using the open() method which opens a file in a new document, then duplicate the layer of the new document into the original document. An example of this can be seen below.
// open new document
var originalDoc = app.activeDocument;
var doc = open( new File( filePath ) );
// duplicate to original document
var layer = doc.activeLayer;
var newLayer = layer.duplicate(originalDoc, ElementPlacement.PLACEATBEGINNING);
// close new document
doc.close(SaveOptions.DONOTSAVECHANGES);
This method is extraordinarily slow, especially for large images. After doing some Googling I discovered that Photoshop has a built-in method for creating an image stack. This feature uses a .jsx script itself and it can be found on GitHub. Looking around online I found a few people trying to load a folders contents as layers, perfect. The main code I was interested in is below.
var folder = new Folder('~/Desktop/MyFolder');
function runLoadStack(folderPath) {
var loadLayersFromScript = true;
// #include 'Load Files into Stack.jsx'
var fList = folder.getFiles('*.png')
var aFlag = true;
loadLayers.intoStack(fList, aFlag);
}
runLoadStack(folder)
I immediately noticed the #include method of importing the stack methods, I can not find any official documentation for this (also not friendly with minification). Also, if the script is not placed with the same directory as Load Files into Stack.jsx it will throw the error Unable to open file: anonymous. And even after solving all of these issues when I run the .jsx script from within my extension using $.evalFile() I am having the same error as if the script is not in the correct directory: Unable to open file: anonymous. Error is being thrown on line 762 of an imported jsx.
Any help resolving the error I am experiencing or simply on how to load an array of image paths into layers (faster method) will be greatly appreciated!
Here is the code I am using within my extension:
var loadLayersFromScript = true;
var strPresets = localize("$$$/ApplicationPresetsFolder/Presets=Presets");
var strScripts = localize("$$$/PSBI/Automate/ImageProcessor/Photoshop/Scripts=Scripts");
var jsxFilePath = app.path + "/" + strPresets + "/" + strScripts + "/Load Files into Stack.jsx";
$.evalFile( new File( jsxFilePath ) );
loadLayers.intoStack( new Folder("/c/Users/Me/teststack").getFiles(), true );
Photoshop's inbuilt scripts has a script to do this here's the github link
https://github.com/ES-Collection/Photoshop-Scripts/blob/master/Import%20Folder%20As%20Layers.jsx
use this script inside your CEP extension

I need to overwrite an existing Google Sheets file with an attached Script

I have a Google Sheets file with an attached Script. The script does a number of things, one is it makes a clone of it self using makeCopy. This portion works. Now I want to be able to keep the same cloned Google file name and same Google file ID and just update the content which includes a Spreadsheet and the associated Google script.
if (!fileFound){
var file = masterSSFile.makeCopy(reportFileName, RepFolder);
} else {
oldFile.setContent(masterSSFile.getBlob());
}
When I use makeCopy with the same file name it creates a second file with the same name but with a different file ID.
The else portion fails because .setContent argument seems to just accept text. The result is the word "Blob" in the oldFile, everything else is gone.
I have other scripts that update the contents of a existing spreadsheet by overriding the contents of the various sheets, but I also want the associated script to also be included in the updated file keeping the same file ID.
I found this....
Overwrite an Image File with Google Apps Script
and tried using
var masterSpreadsheetID = SpreadsheetApp.getActiveSpreadsheet().getId();
var masterSpreadsheetFile = DriveApp.getFileById(masterSpreadsheetID);
var oldFileID = oldFile.getId();
var oldFileName = oldFile.getName();
var newBlob = masterSpreadsheetFile.getBlob();
var file = {
title: oldFileName,
mimeType: 'application/vnd.google-apps.spreadsheet'
};
var f = Drive.Files.update(file, oldFileID, newBlob);
I get error: "We're sorry, a server error occurred. Please wait a bit and try again. " on this line: "Drive.Files.update(file, oldFileID, newBlob);"
After reading this:
https://github.com/google/google-api-nodejs-client/issues/495
it looks like Drive.Files.update(), does not support bound scripts.

Paper.js Server-Side Can't Work with Received Layers

In an effort to reduce clientside load, we are attempting to do the work of flattening Paper.js layers on a Node Express server. We have many layers to flatten with lots of image data. And rather than overwriting our data structure, we want to end up with new objects containing the rasterized (flattened) layers.
So we have an Express route that looks like this:
app.post('/flatten', function (request, response) {
var pdfs = JSON.parse(request.body.pdfs);
// Attempt to set up canvas on the server side to work with
var canvas = new paper.Canvas(1000, 1000);
paper.setup(canvas);
paper.view.draw();
for (var i = 0; i < pdfs.length; i++) {
var pdf = pdfs[i];
if (pdf !== null) {
for (var j = 0; j < pdf.pages.length; j++) {
if (pdf.pages[j].layer !== undefined) {
paper.project.layers.push(pdf.pages[j].layer); // Attempt to add to current project; necessary?
pdf.pages[j].layer.activate(); // Blows up
pdf.pages[j].layer.visible = true;
var layerAsRaster = pdf.pages[j].layer.rasterize(); // Blows up
layerAsRaster.visible = false;
var dataString = layerAsRaster.toDataURL();
pdfs[i].pages[j].pageImageData = dataString.split(',')[1];
pdf.pages[j].layer.visible = false;
}
}
}
}
response.send(pdfs);
});
The .layer is a native Paper.js layer that was made on the clientside.
We receive this error when hitting this route:
TypeError: pdf.pages[j].layer.activate is not a function
Thinking that perhaps we don't need to worry about activating layers on the serverside, I commented that out, but got the same error for the .rasterize line. (See the two lines commented "Blows up".)
Do I need to somehow import the layers we're receiving from the client into the project? I attempt to do that with the line:
paper.project.layers.push(pdf.pages[j].layer);
but to no avail.
How can I modify this method to successfully work with layers on the serverside?
The problem is that you are directly adding the layer to the project with the line paper.project.layers.push(pdf.pages[j].layer);
You're not allowed to directly manipulate paper's data structures. If you want to add a layer to a project use the following (note that this is not documented and will change with the next release of paper, but I don't think you'll need to do this):
(paperscript)
project.addChild(layer);
(javascript)
paper.project.addChild(layer);
It's not clear how pdf.pages[i].layer was created on the server side, whether it was imported via JSON (in which case it could already be inserted into the project), or whether it was removed from another project, so there may be other complications.
I think there is another problem. It doesn't appear that pdf.pages[i].layer has been turned into a server-side layer. So the key question is how was it transferred from the client to the server?
Here's a stab at the whole process:
(client side)
jsonLayer = paper.project.activeLayer.exportJSON();
// send jsonLayer to server using some method
(server side)
// get jsonLayer from client
layer = new paper.Layer();
layer.importJSON(jsonLayer);
layer should already be inserted into the project and should contain all the items that were in jsonLayer which was the layer on the client.
Here's a link to a discussion on how importJSON and exportJSON map to one another:
paperjs group discussion

Real-time basic web analytics with Javascript

I need to develop an in-house real-time analytics solution (similar to GA or mixpanel for example) that collects:
Information from the website itself ­­(URL)
Information from the user’s browser ­­(lang, device, OS etc..)
Information from the referring source etc..
.. and sends this data to the server with a single-pixel image request. Similar to how GA and other solutions work:
Google Analytics works by the inclusion of a block of JavaScript code
on pages in your website. When users to your website view a page, this
JavaScript code references a JavaScript file which then executes the
tracking operation for Analytics. The tracking operation retrieves
data about the page request through various means and sends this
information to the Analytics server via a list of parameters attached
to a single-pixel image request.
I wonder if there's any open source project available that does this part which I could use as base to build further. There's Piwik but its too feature-packed and too heavy for my requirement.
Edited to add: I'm doing something specific with the data, otherwise I'd just use the existing solutions.
Try
var img = new Image;
img.width = img.height = "1px";
var res = window.navigator;
var data = {};
var _plugins = {};
Array.prototype.slice.call(navigator.plugins).forEach(function(v, k) {
_plugins[v.name.toLowerCase().replace(/\s/, "-")] = {
"name": v.name,
"description": v.description,
"filename": v.filename
}
});
delete res.plugins && delete res.mimeTypes;
data.url = window.location.href;
data.ref = document.referrer;
data.nav = res;
data._plugins = _plugins;
// set `img` `dataset` with `data` ,
// send `img` to server , decode `img` `dataset` at server
img.dataset.stats = JSON.stringify(data);
var img = new Image;
img.width = img.height = "1px";
var res = window.navigator;
var data = {};
var _plugins = {};
Array.prototype.slice.call(navigator.plugins).forEach(function(v, k) {
_plugins[v.name.toLowerCase().replace(/\s/, "-")] = {
"name": v.name,
"description": v.description,
"filename": v.filename
}
});
delete res.plugins && delete res.mimeTypes;
data.url = window.location.href;
data.ref = document.referrer;
data.nav = res;
data._plugins = _plugins;
img.dataset.stats = JSON.stringify(data);
document.write(
img.dataset.stats
);
There are 2 big solutions for open source analytics.
Piwik as you mentioned is a well documented and pretty mature solution. Drilling down the code, how Piwik makes things come around will give you some insights.
Open Web Analytics is the other big player on the game. A more simplified tool which will help you understand how basic tracking is made.
Depending on the data you want to track I would also suggest taking a look on this tutorial which uses sockets in order to track real time data.
Least but not last you can also check what Crazy Egg does if you want to track down user's interactivity.

Categories

Resources