Geolocation, latitude and longitude not defined after first call - javascript

I have a button that calls a function called HomeTest(). Within that function I call geoFindMe(), a simple geolocation function. This geoFindMe() gives me a var latitude and var longitude. Within the HomeTest() I use these variables to see whether I am in a certain polygon.
If I am in the right polygon, the button should change to another .html-file
My problem is, that I have to press the button TWICE to make the site load on the new .html-file, as it doesn't seem to get the latitude & longitude variables with the first try, even though I'm calling the geoFindMe() before using the variables. I'm a little new to js so I'm not quite sure why I don't get relocated to the new .html-file after one click when I am in the correct area.
Somebody got any idea?
function geoFindMe() {
if (!navigator.geolocation){
output.innerHTML = "<p>Your browser doesn't support geolocation.</p>";
return;
}
function success(position) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
};
function error() {
output.innerHTML = "The site was not able to locate you";
alert("Please use another browser.");
};
navigator.geolocation.getCurrentPosition(success, error);
}
function HomeTest(){
geoFindMe();
var polygon = [ [ longitude1, latitude1], [ longitude2, latitude2], [ longitude3, latitude3], [ longitude4, latitude4] ];
insideTest([ longitude, latitude ], polygon); // true -> point coordinates that are searched
//alert("is inside is " + isInsideTest + " " + latitude + " " + longitude);
//Test_LockButton();
if(isInsideTest){
location.href = './html/testhome.html';
}
}
This is the function that checks, wether the latitude&longitude are within the 4 points of the polygon (see above)
function insideTest(point, vs) {
var x = point[0], y = point[1];
for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
var xi = vs[i][0], yi = vs[i][1];
var xj = vs[j][0], yj = vs[j][1];
var intersect = ((yi > y) != (yj > y))
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) isInsideTest = !isInsideTest;
}
return isInsideTest;
}

It's a simple enough issue that's causing you this grief, the getCurrentPosition function is asynchronous, meaning that you don't have the result by the time you call insideTest. When you click the second time, the variables have been stored and everything works as expected. If you put a delay of a few hundred milliseconds before calling insideTest everything would be OK, however this is not very good practice, it's better to define a callback function to call when the position is available, here's an example:
function insideTest(point, vs) {
var isInsideTest = false;
var x = point[0], y = point[1];
for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
var xi = vs[i][0], yi = vs[i][1];
var xj = vs[j][0], yj = vs[j][1];
var intersect = ((yi > y) != (yj > y))
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) isInsideTest = !isInsideTest;
}
return isInsideTest;
}
function geoFindMe(successCallback) {
if (!navigator.geolocation){
output.innerHTML = "<p>Your browser doesn't support geolocation.</p>";
return;
}
function success(position) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
successCallback();
};
function error() {
output.innerHTML = "The site was not able to locate you";
alert("Please use another browser.");
};
navigator.geolocation.getCurrentPosition(success, error);
}
function homeTestCallback() {
var polygon = [ [ longitude1, latitude1], [ longitude2, latitude2], [ longitude3, latitude3], [ longitude4, latitude4] ];
var isInsidePolygon = insideTest([ longitude, latitude ], polygon);
if(isInsidePolygon) {
location.href = './html/testhome.html';
}
}
function HomeTest() {
// Pass in a function to call when the position is ready
geoFindMe(homeTestCallback);
}

Related

check if a lat long is within an extent using open layers 3

I have a UK county shape file (Multipolygon) using EPSG:4326 in my geoserver. I'm using open layers 3 to load this shape file in my application as below :
source = new ol.source.XYZ({url: '/gmaps?zoom={z}&x={x}&y={y}&Layers=UKCounties', crossOrigin: "anonymous"});
countiesLayer = new ol.layer.Tile({source: source});
map.addLayer(countiesLayer);
This works well. I have a requirement to get users current location which is done as
var coordinate = geolocation.getPosition();
I'm able to retrieve the correct lat & long here. Ex : Lat = 53.797534899999995, Lng = -1.5449. now I need to check which of the counties (polygon) these points are in using open layers 3 & Javascript.
Using Geoserver WFS, I'm able to get the bounding box of each of the counties as
$.each(features, function(index, eachFeature) {
var bbox = eachFeature.properties.bbox;
if (bbox != null) {
var bottomLeft = ([bbox[0], bbox[1]]);
var topRight = ([bbox[2], bbox[3]]);
var extent = new ol.extent.boundingExtent([bottomLeft, topRight]);
if (ol.extent.containsXY(extent1,lat,long)) {
alert("got the feature");
}
}
});
The issue is my code doesn't print the alert statement.I've also tried using
if (ol.extent.containsXY(extent,long,lat))
and
var XY = ol.proj.transform([long, lat], 'EPSG:4326', 'EPSG:3857');
if (ol.extent.containsXY(extent,XY[0],XY[1]))
if (ol.extent.containsXY(extent,XY[1],XY[0]))
But none of these print the alert. Is there anything wrong in this?
Before answering your question, I did not know the method of "ol.extent.containsXY".
I used my poor logic! I detected a feature if in a polygon by follwing :
transform feature and container(polygon) to coordinate [lon, lat]
detect the container if contain the feature
extent array rule [minLon, minLat, maxLon, maxLat]
code snippet: (my destinationPro:'EPSG:3857', sourcePro:'EPSG:4326')
QyGIS.prototype.isInner = function(featureExtent, containerExtent) {
var featureLonLat = ol.proj.transformExtent(featureExtent, destinationPro, sourcePro);
var containerLonLat = ol.proj.transformExtent(containerExtent, destinationPro, sourcePro);
// in my condition, the feature is a point, so featureLonLat[0] = featureLonLat[2], featureLonLat[1] = featureLonLat[3]. what's more extent have four value in a array so the loop length is 4
for (var i = 0; i < featureLonLat.length; i++) {
/* actually:
featureLonLat[0] < containerLonLat[0] || featureLonLat[0] > containerLonLat[2]
featureLonLat[1] < containerLonLat[1] || featureLonLat[1] > containerLonLat[3]
featureLonLat[2] < containerLonLat[0] || featureLonLat[2] > containerLonLat[2]
featureLonLat[3] < containerLonLat[1] || featureLonLat[3] > containerLonLat[3]
*/
if (featureLonLat[i] < containerLonLat[i % 2] || featureLonLat[i] > containerLonLat[i % 2 + 2]) {
return false;
}
}
return true;
};
QyGIS.prototype.getInnerFeatures = function(layerName, extent) {
var self = this;
var layer = self.getLayer(layerName);
if (layer) {
var source = layer.getSource();
var features = source.getFeatures();
for (var i = 0; i < features.length; i++) {
var curFeatureExtent = features[i].getGeometry().getExtent();
if (self.isInner(curFeatureExtent, extent)) {
console.log(features[i].get('name') + 'in area');
}
}
}
};
At last, sorry for my poor english if my answer confuse you .
I had to use
var XY = ol.extent.applyTransform(extent, ol.proj.getTransform("EPSG:3857", "EPSG:4326"));
instead of
var XY = ol.proj.transform([long, lat], 'EPSG:4326', 'EPSG:3857');
and it works.

Display certain posts based on User Location

I'm trying to figure out how to display certain mongoDB posts depending on the user's location. I have set up a search functionality that lets people search for MongoDB posts. I also have figured out how to get a user's location and find a big city near them.
Let's say you're in Washington DC. I want only posts containing Washington DC in the title to show up on a "show" page. I've been unable to figure this out.
Any advice?
Thanks!
Node & MongoDB set up to handle search request:
router.get("/", function(req, res){
if (req.query.search) {
const regex = new RegExp(req.query.search, 'i');
Deals.find({ "name": regex }, function(err, founddeals) {
if(err){
console.log(err);
} else {
res.render("deals/index",{deals:founddeals});
}
});
}
Set up to get the user's location.
This also returns the city nearest to the user
// Get User's Coordinate from their Browser
window.onload = function() {
// HTML5/W3C Geolocation
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(UserLocation);
}
// Default to Washington, DC
else
NearestCity(38.8951, -77.0367);
}
// Callback function for asynchronous call to HTML5 geolocation
function UserLocation(position) {
NearestCity(position.coords.latitude, position.coords.longitude);
}
// Convert Degress to Radians
function Deg2Rad(deg) {
return deg * Math.PI / 180;
}
function PythagorasEquirectangular(lat1, lon1, lat2, lon2) {
lat1 = Deg2Rad(lat1);
lat2 = Deg2Rad(lat2);
lon1 = Deg2Rad(lon1);
lon2 = Deg2Rad(lon2);
var R = 6371; // km
var x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
var y = (lat2 - lat1);
var d = Math.sqrt(x * x + y * y) * R;
return d;
}
var lat = 20; // user's latitude
var lon = 40; // user's longitude
var cities = [
["ATL", 33.740231, -84.394521],
["NYC", 40.748163, -73.985946],
["Vegas", 34.825425, -82.545665]
];
function NearestCity(latitude, longitude) {
var mindif = 99999;
var closest;
for (index = 0; index < cities.length; ++index) {
var dif = PythagorasEquirectangular(latitude, longitude, cities[index][1], cities[index][2]);
if (dif < mindif) {
closest = index;
mindif = dif;
}
}
// echo the nearest city
alert(cities[closest]);
console.log(closest)
}
I Hope you are using mongoose. Please try this code in your server. I have used $regex and made a small modification for your code.
router.get("/", function(req, res){
if (req.query.search) {
Deals.find({ "name":{ $regex: req.query.search } }, function(err, founddeals) {
if(err){
console.log(err);
} else {
res.render("deals/index",{deals:founddeals});
}
});
}

getBoundingClientRect of SVG Path not working

I am making a library for Google Geo Charts on click zooming (API != zoom)
I need to get the width or height of the svg paths so I can filter them and store their coordinates in an array object. I was able to store alaska and hawaii g elements coords but with the continental US I have to go one level deeper to path and am having a hard time realizing where I am going wrong.
I am getting undefined on the continental nodeList.
google.visualization.events.addOneTimeListener(chart, 'ready', function (e){
google.visualization.events.addListener(chart, 'select', function (e){
var selection = chart.getSelection(),
selectedState = '',
nodes = document.querySelectorAll("g[clip-path]")[0].childNodes[0],
continental = nodes.childNodes[0],
alaska = nodes.childNodes[1],
hawaii = nodes.childNodes[2],
stateCoords = {},
nl = null,
zoomX = null,
zoomY = null;
//////////////////////////////
//Get Coordinates of States//
/////////////////////////////
getCoords(alaska);
getCoords(hawaii);
// getCoords(continental);
console.log(stateCoords);
function getCoords(nodeList){
function getZoom(nodeList, s){
nl = nodeList.getBoundingClientRect();
zoomY = nl.top + (nl.height/2);
zoomX = nl.left + (nl.width/2);
stateCoords[s] = [zoomX, zoomY];
}
if (nodeList == alaska) {
getZoom(nodeList, 1);
}
else if (nodeList == hawaii){
getZoom(nodeList, 11);
}
else {
console.log('continental');
var nodeListLength = nodeList.childNodes.length,
i = 0,
s = 0;
for (i; i < nodeListLength; i++) {
console.log(nodeList.childNodes[i]);
var pathBound = nodeList.childNodes[i].getBoundingClientRect();
if (pathBound.height > 3 && s != 1 && s!= 11) {
getZoom(nodeList[i], s);
s++;
} else { s++; }
}
}
}

Uncaught TypeError: object is not a function on object creation

function coordinate(x, y) {
this.x = x,
this.y = y
}
function generateBaracade(numBlocks) {
var coordinate = getRandomBaracadeCoordinate();
var xStyle = expandDirection.down;
var yStyle = expandDirection.right;
var xNumBlocks = findRandomFactor(numBlocks);
var yNumBlocks = numBlocks / xNumBlocks;
//figure out which way to expand the blocks
if (coordinate.x + xNumBlocks > xBlocks) {
xStyle = expandDirection.left;
} else {
xStyle = expandDirection.right;
}
if (coordinate.y + yNumBlocks > yBlocks) {
yStyle = expandDirection.down;
} else {
yStyle = expandDirection.up;
}
for (var i = 0; i <= xNumBlocks - 1; i++) {
for (var j = 0; j <= yNumBlocks - 1; j++) {
var tempBlock = Object.create(block);
tempBlock.type = "obstruction";
tempBlock.color = "grey";
tempBlock.illegalTerrain = true;
tempBlock.coordinate = new coordinate(coordinate.x + (i * xStyle), coordinate.y + (j * yStyle));
blockContainer[coordinate.x + (i * xStyle)][coordinate.y + (j * yStyle)] = tempBlock;
};
};
}
I get the 'Uncaught TypeError: object is not a function' on the line:
tempBlock.coordinate = new coordinate(coordinate.x + (i * xStyle), coordinate.y + (j * yStyle));
This is strange as I am following the mozilla guide to doing this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new
EDIT: Source for getRandomBaracadeCoordinate. The return statement is exactly what I want to do, and executes without error.
function getRandomBaracadeCoordinate() {
var x = Math.floor((Math.random() * (xBlocks)));
var y = Math.floor((Math.random() * (yBlocks)));
return new coordinate(x, y);
}
You are shadowing the coordinate function by giving something else the same name on the first line of getBaracade:
var coordinate = getRandomBaracadeCoordinate();
Whatever getRandomBaracadeCoordinate() returns isn't a function, so new coordinate throws an error.
coordinate is an object containing { x, y } and initialized here:
var coordinate = getRandomBaracadeCoordinate();
 
tempBlock.coordinate = new coordinate(coordinate.x + (i * xStyle), coordinate.y + (j * yStyle));
Probably you mistyped new coordinate() instead of new Coordinate() (if Coordinate is a class).
You should look at the source of getRandomBaracadeCoordinate() — if it returns an object of some class, you should create an instance of this class. Otherwise, if it returns a simple { x:50, y:15 } object, you can create it inline:
tempBlock.coordinate = { x: coordinate.x + (i * xStyle), y: coordinate.y + (j * yStyle) };

JavaScript "null or not an object" error

I'm running the JavaScript below to place horizontal scrolling text on the banner of my website. It works in one server but not another. I get the following error:
Error: 'this.mqo' is null or not an object
JavaScript:
function start() {
new mq('m1');
/* new mq('m2');
*/
mqRotate(mqr); // must come last
}
window.onload = start;
// Continuous Text Marquee
// permission to use this Javascript on your web page is granted
// provided that all of the code below in this script (including these
// comments) is used without any alteration
function objWidth(obj) {
if (obj.offsetWidth) return obj.offsetWidth;
if (obj.clip) return obj.clip.width;
return 0;
}
var mqr = [];
function mq(id) {
this.mqo = document.getElementById(id);
var wid = objWidth(this.mqo.getElementsByTagName('span')[0]) + 5;
var fulwid = objWidth(this.mqo);
var txt = this.mqo.getElementsByTagName('span')[0].innerHTML;
this.mqo.innerHTML = '';
var heit = this.mqo.style.height;
this.mqo.onmouseout = function () {
mqRotate(mqr);
};
this.mqo.onmouseover = function () {
clearTimeout(mqr[0].TO);
};
this.mqo.ary = [];
var maxw = Math.ceil(fulwid / wid) + 1;
for (var i = 0; i < maxw; i++) {
this.mqo.ary[i] = document.createElement('div');
this.mqo.ary[i].innerHTML = txt;
this.mqo.ary[i].style.position = 'absolute';
this.mqo.ary[i].style.left = (wid * i) + 'px';
this.mqo.ary[i].style.width = wid + 'px';
this.mqo.ary[i].style.height = heit;
this.mqo.appendChild(this.mqo.ary[i]);
}
mqr.push(this.mqo);
}
function mqRotate(mqr) {
if (!mqr) return;
for (var j = mqr.length - 1; j > -1; j--) {
maxa = mqr[j].ary.length;
for (var i = 0; i < maxa; i++) {
var x = mqr[j].ary[i].style;
x.left = (parseInt(x.left, 10) - 1) + 'px';
}
var y = mqr[j].ary[0].style;
if (parseInt(y.left, 10) + parseInt(y.width, 10) < 0) {
var z = mqr[j].ary.shift();
z.style.left = (parseInt(z.style.left) + parseInt(z.style.width) * maxa) + 'px';
mqr[j].ary.push(z);
}
}
mqr[0].TO = setTimeout('mqRotate(mqr)', 10);
}
The reason is most likely that there is no element with the id "m1". Place this line first in the start function to diagnose this:
alert(document.getElementById('m1'));
If it shows "[Object]" (or similar), the element exists and it's some other problem, but if it shows "undefined" it means that there is no such element in the page.

Categories