NetworkError: 414 Request-URI Too Large with Google Maps v3 - google-maps

My application create map using Google Maps v3 that have lots of markers and clusters on it, and it works fine.
Same map I have to show also in another browser window, but for some reason it can't (getting only empty map, without markers/clusters on it). I checked error in Firebug, and there is an message:
NetworkError: 414 Request-URI Too Large
So - same maps, in first browser window is ok, in second it is not.
Just to say that I'm opening second map (in second window) by sending parameters about every marker I have on first map, so URL is very long (2700 characters).
Is there some way to solve this? Is it a problem with long url string?
Can you help me with this?

The problem is in the URL you generated. Google specifies a limit of 2000 chars for the passed URL and we should stick with it.
I solved the problem in my application by generating a hash of the URL before passing it over to Google.
1) Create a database table to store your hashes. Columns can be hash, params, timestamp. You can improve your code by deleting hashes older than certain time, keeping the table small and fast.
2) Create a code (my_google_map_helper/get_hash) to generate the hash to be passed to Google and stick it somewhere. I am using PHP, so my code is:
// generate my hash
$hash = sha1(serialize($_GET));
// run an insert ignore into my hashes' table
// get the hash where the hash is $hash
// print my hash
3) Create a code (get_kml) to retrieve the params saved into the database from a given hash
if(isset($_GET['hash'])):
// select params from my hash table where hash = $_GET['hash']
// unserialize the saved params
// generate and return my KML file
endif;
4) Change your JavaScript so it generates the hash before calling the Google function:
$.get('my_google_map_helper/get_hash?' + MY_LONG_PARAMS_LIST, true)
, function(hash){
Polygons = new google.maps.KmlLayer(
{url:'http://my_url/get_kml?hash=' + hash , map:MAP}
);
}
);
Have fun!

Related

Apps script JSON.parse() returns unexpected result, how can I solve this?

I am currently working on external app using Google Sheets and JSON for data transmission via Fetch API. I decided to mock the scenario (for debugging matters) then simple JSON comes from my external app through prepared Code.gs to be posted on Google sheets. The code snippet I run through Apps-scripts looks like this:
function _doPost(/* e */) {
// const body = e.postData.contents;
const bodyJSON = JSON.parse("{\"coords\" : \"123,456,789,112,113,114,115,116\"}" /* instead of : body */);
const db = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
db.getRange("A1:A10").setValue(bodyJSON.coords).setNumberFormat("#"); // get range, set value, set text format
}
The problem is the result I get: 123,456,789,112,113,000,000,000 As you see, starting from 114 and the later it outputs me 000,... instead. I thought, okay I am gonna explicitly specify format to be returned (saved) as a text format. If the output within the range selected on Google Sheets UI : Format -> Number -> it shows me Text.
However, interesting magic happens, let's say if I would update the body of the JSON to be parsed something like that when the sequence of numbers composed of 2 digits instead of 3 (notice: those are actual part of string, not true numbers, separated by comma!) : "{\"coords\" : \"123,456,789,112,113,114,115,116,17,18\"}" it would not only show response result as expected but also brings back id est fixes the "corrupted" values hidden under the 000,... as so : "{"coords" : "123,456,789,112,113,114,115,116,17,18 "}".
Even Logger.log() returns me initial JSON input as expected. I really have no clue what is going on. I would really appreciate one's correspondence to help solving this issue. Thank you.
You can try directly assigning a JSON formatted string in your bodyJSON variable instead of parsing a set of string using JSON.parse.
Part of your code should look like this:
const bodyJSON = {
"coords" : "123,456,789,112,113,114,115,116"
}
I found simple workaround after all: just added the preceding pair of zeros 0,0,123,... at the very beginning of coords. This prevents so called culprit I defined in my issue. If anyone interested, the external app I am building currently, it's called Hotspot widget : play around with DOM, append a marker which coordinates (coords) being pushed through Apps-script and saved to Google Sheets. I am providing a link with instructions on how to set up one's own copy of the app. It's a decent start-off for learning Vanilla JavaScript basics including simple database approach on the fly. Thank you and good luck!
Hotspot widget on Github

Spatial functions and Google Maps

I have a Google Map where I'd like to display some markers etc.
If you open the website, it sets session to "geometrycollection empty". When the map is fully loaded, it makes an AJAX request with NE & SW lat and lng as parameters.
Handle method for AJAX looks like that:
$contain = $this->locationsManager->getContainOfAreas($this->getSession("union")->area, $polygon);
$area = $this->locationsManager->getDifferentiatedArea($polygon, $this->getSession("union")->area);
$coordinates = $this->locationsManager->getLocationsCoordinates($area["polygon"]);
$this->getSession("union")->area = $this->locationsManager->getUnionOfAreas($this->getSession("union")->area, $area["polygon"])["unionArea"];
But when I try to find out if area B ($this->getSession("union")->area - union of areas (viewports) user "visited") contains area A ($polygon - current viewport in Google Maps), it returns wrong results (I drew polygons from the variables via Google Maps Polygons and they were different).
This is SQL command for getting result of getContainOfAreas:
SELECT ST_CONTAINS(ST_GEOMFROMTEXT(?), ST_GEOMFROMTEXT(?)) AS result;
Do you know what I'm doing wrong?

How to display a 2-D array as an html table for a Google Web App Page (using GAS)

Using a code.gs file, I have retrieved data from a Google Spreadsheet and put it into a 2-D array, and then manipulated the array a little bit (with things like transpose, condensing it, etc.).
I am trying to find out how to create a web app / web page that will display this 2-D array as an html table (subject to also being able to set table specifications, like width, color, etc.).
Does anyone have any ideas on how this can be done?
This will tell you how to do it, generally speaking. Just to display the HTML.
https://developers.google.com/apps-script/guides/html/
To choose specific data, you will want to use the .gs file to grab the spread sheet as you have already done. Now, when you're done modifying your array, store it in Properties Service, or Cache Service.
In your HTML page, write a JS function that calls back to the .gs file.
google.script.run
.withSuccessHandeler( function(array) { ... //We'll get to this in a moment... })
.getMyArray();
In your .gs file, write a function 'getMyArray'. Make it retrieve the array from Property or Cache Service and make it return the array.
Now, it the Success Handeler, use your array, and make it a table.
// 'array' here will be the return of .getMyArray()
.withSuccessHandler( function(array) {
for (var i in array) {
// Here, make every object into a string of the table you want
// i.e. "<table><td>" + array[i] + "<td> ..."
// Insert that string into some div.innerHTML
}
.getMyArray();
Easy as pi

Google Maps data not being read in by jQuery .tablesorter()

I'm using Google Maps to calculate distances between a user-entered address and our store locations. Once this data is read in, I'd like to use jQuery .tablesorter() to sort the table from closest to furthest store. However, the data read in from Google Maps is not being recognized by the jQuery .tablesorter() function. I tried implementing the setTimeout() suggestion on this thread (JQuery tablesorter appended data not sorting) and numerous other fixes that did not work. I understand what's happening (the DOM not recognizing data written to the page after it's been constructed), but I'm not entirely sure how to fix it. Any ideas? Thanks!
Here's the URL to the test page if you'd like to see what's happening: http://www.gregcklotz.com/Larry/Locations.php
You just need to update the table after adding all of the distance data into the columns:
for (i = 0; i < stores.length; i++)
{
address = new google.maps.LatLng(lat, lng);
coords = new google.maps.LatLng(stores[i].lat, stores[i].long);
distance = (.621371192237334 * google.maps.geometry.spherical.computeDistanceBetween(address, coords)/1000).toFixed(1);
$("tr.store"+stores[i].store+" td:last").text(parseInt(distance));
}
// update the table data
$("table").trigger("update");
map.setCenter(marker.getPosition());

Using Other Data Sources for cubism.js

I like the user experience of cubism, and would like to use this on top of a backend we have.
I've read the API doc's and some of the code, most of this seems to be extracted away. How could I begin to use other data sources exactly?
I have a data store of about 6k individual machines with 5 minute precision on around 100 or so stats.
I would like to query some web app with a specific identifier for that machine and then render a dashboard similar to cubism via querying a specific mongo data store.
Writing the webapp or the querying to mongo isn't the issue.
The issue is more in line with the fact that cubism seems to require querying whatever data store you use for each individual data point (say you have 100 stats across a window of a week...expensive).
Is there another way I could leverage this tool to look at data that gets loaded using something similar to the code below?
var data = [];
d3.json("/initial", function(json) { data.concat(json); });
d3.json("/update", function(json) { data.push(json); });
Cubism takes care of initialization and update for you: the initial request is the full visible window (start to stop, typically 1,440 data points), while subsequent requests are only for a few most recent metrics (7 data points).
Take a look at context.metric for how to implement a new data source. The simplest possible implementation is like this:
var foo = context.metric(function(start, stop, step, callback) {
d3.json("/data", function(data) {
if (!data) return callback(new Error("unable to load data"));
callback(null, data);
});
});
You would extend this to change the "/data" URL as appropriate, passing in the start, stop and step times, and whatever else you want to use to identify a metric. For example, both Cube and Graphite use a metric expression as an additional query parameter.