Problem getting my correct location with google chrome Javascript - javascript

I have the following code which is responsible for the geographical location of latitude, longitude and the map of where one is:
<html>
<head>
<title>javascript-mobile-desktop-geolocation With No Simulation with Google Maps</title>
<meta name = "viewport" content = "width = device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;">
<style>
body {font-family: Helvetica;font-size:11pt;padding:0px;margin:0px}
#title {background-color:#e22640;padding:5px;}
#current {font-size:10pt;padding:5px;}
</style>
</head>
<body onload="initialiseMap();initialise()">
<h1>location GPS</h1>
<div id="current">Initializing...</div>
<div id="map_canvas" style="width:320px; height:350px"></div>
<script src="js/geoPosition.js" type="text/javascript" charset="utf-8">
</script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script>
function initialiseMap()
{
var myOptions = {
zoom: 4,
mapTypeControl: true,
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
navigationControl: true,
navigationControlOptions: {style: google.maps.NavigationControlStyle.SMALL},
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
}
function initialise()
{
if(geoPosition.init())
{
document.getElementById('current').innerHTML="Receiving...";
geoPosition.getCurrentPosition(showPosition,function(){document.getElementById('current').innerHTML="Couldn't get location"},{enableHighAccuracy:true});
}
else
{
document.getElementById('current').innerHTML="Functionality not available";
}
}
function showPosition(p)
{
var latitude = parseFloat( p.coords.latitude );
var longitude = parseFloat( p.coords.longitude );
document.getElementById('current').innerHTML="latitude=" + latitude + " longitude=" + longitude;
var pos=new google.maps.LatLng( latitude , longitude);
map.setCenter(pos);
map.setZoom(14);
var infowindow = new google.maps.InfoWindow({
content: "<strong>yes</strong>"
});
var marker = new google.maps.Marker({
position: pos,
map: map,
title:"You are here"
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
}
</script>
</body>
</html>
the file geoPosition.js:
var bb = {
success: 0,
error: 0,
blackberryTimeoutId : -1
};
function handleBlackBerryLocationTimeout()
{
if(bb.blackberryTimeoutId!=-1) {
bb.error({ message: "Timeout error",
code: 3
});
}
}
function handleBlackBerryLocation()
{
clearTimeout(bb.blackberryTimeoutId);
bb.blackberryTimeoutId=-1;
if (bb.success && bb.error) {
if(blackberry.location.latitude==0 && blackberry.location.longitude==0) {
//http://dev.w3.org/geo/api/spec-source.html#position_unavailable_error
//POSITION_UNAVAILABLE (numeric value 2)
bb.error({message:"Position unavailable", code:2});
}
else
{
var timestamp=null;
//only available with 4.6 and later
//http://na.blackberry.com/eng/deliverables/8861/blackberry_location_568404_11.jsp
if (blackberry.location.timestamp)
{
timestamp = new Date( blackberry.location.timestamp );
}
bb.success( { timestamp: timestamp ,
coords: {
latitude: blackberry.location.latitude,
longitude: blackberry.location.longitude
}
});
}
//since blackberry.location.removeLocationUpdate();
//is not working as described http://na.blackberry.com/eng/deliverables/8861/blackberry_location_removeLocationUpdate_568409_11.jsp
//the callback are set to null to indicate that the job is done
bb.success = null;
bb.error = null;
}
}
var geoPosition=function() {
var pub = {};
var provider=null;
var u="undefined";
var ipGeolocationSrv = 'http://freegeoip.net/json/?callback=JSONPCallback';
pub.getCurrentPosition = function(success,error,opts)
{
provider.getCurrentPosition(success, error,opts);
}
pub.jsonp = {
callbackCounter: 0,
fetch: function(url, callback) {
var fn = 'JSONPCallback_' + this.callbackCounter++;
window[fn] = this.evalJSONP(callback);
url = url.replace('=JSONPCallback', '=' + fn);
var scriptTag = document.createElement('SCRIPT');
scriptTag.src = url;
document.getElementsByTagName('HEAD')[0].appendChild(scriptTag);
},
evalJSONP: function(callback) {
return function(data) {
callback(data);
}
}
};
pub.confirmation = function()
{
return confirm('This Webpage wants to track your physical location.\nDo you allow it?');
};
pub.init = function()
{
try
{
var hasGeolocation = typeof(navigator.geolocation)!=u;
if( !hasGeolocation ){
if( !pub.confirmation() ){
return false;
}
}
if ( ( typeof(geoPositionSimulator)!=u ) && (geoPositionSimulator.length > 0 ) ){
provider=geoPositionSimulator;
} else if (typeof(bondi)!=u && typeof(bondi.geolocation)!=u ) {
provider=bondi.geolocation;
} else if ( hasGeolocation ) {
provider=navigator.geolocation;
pub.getCurrentPosition = function(success, error, opts)
{
function _success(p) {
//for mozilla geode,it returns the coordinates slightly differently
var params;
if(typeof(p.latitude)!=u) {
params = {
timestamp: p.timestamp,
coords: {
latitude: p.latitude,
longitude: p.longitude
}
};
} else {
params = p;
}
success( params );
}
provider.getCurrentPosition(_success,error,opts);
}
} else if(typeof(window.blackberry)!=u && blackberry.location.GPSSupported) {
// set to autonomous mode
if(typeof(blackberry.location.setAidMode)==u) {
return false;
}
blackberry.location.setAidMode(2);
//override default method implementation
pub.getCurrentPosition = function(success,error,opts)
{
//passing over callbacks as parameter didn't work consistently
//in the onLocationUpdate method, thats why they have to be set outside
bb.success = success;
bb.error = error;
//function needs to be a string according to
//http://www.tonybunce.com/2008/05/08/Blackberry-Browser-Amp-GPS.aspx
if(opts['timeout']) {
bb.blackberryTimeoutId = setTimeout("handleBlackBerryLocationTimeout()",opts['timeout']);
} else {
//default timeout when none is given to prevent a hanging script
bb.blackberryTimeoutId = setTimeout("handleBlackBerryLocationTimeout()",60000);
}
blackberry.location.onLocationUpdate("handleBlackBerryLocation()");
blackberry.location.refreshLocation();
}
provider = blackberry.location;
} else if ( typeof(Mojo) !=u && typeof(Mojo.Service.Request)!="Mojo.Service.Request") {
provider = true;
pub.getCurrentPosition = function(success, error, opts)
{
parameters = {};
if( opts ) {
//http://developer.palm.com/index.php?option=com_content&view=article&id=1673#GPS-getCurrentPosition
if (opts.enableHighAccuracy && opts.enableHighAccuracy == true ){
parameters.accuracy = 1;
}
if ( opts.maximumAge ) {
parameters.maximumAge = opts.maximumAge;
}
if (opts.responseTime) {
if( opts.responseTime < 5 ) {
parameters.responseTime = 1;
} else if ( opts.responseTime < 20 ) {
parameters.responseTime = 2;
} else {
parameters.timeout = 3;
}
}
}
r = new Mojo.Service.Request( 'palm://com.palm.location' , {
method:"getCurrentPosition",
parameters:parameters,
onSuccess: function( p ){
success( { timestamp: p.timestamp,
coords: {
latitude: p.latitude,
longitude: p.longitude,
heading: p.heading
}
});
},
onFailure: function( e ){
if (e.errorCode==1) {
error({ code: 3,
message: "Timeout"
});
} else if (e.errorCode==2){
error({ code: 2,
message: "Position unavailable"
});
} else {
error({ code: 0,
message: "Unknown Error: webOS-code" + errorCode
});
}
}
});
}
}
else if (typeof(device)!=u && typeof(device.getServiceObject)!=u) {
provider=device.getServiceObject("Service.Location", "ILocation");
//override default method implementation
pub.getCurrentPosition = function(success, error, opts){
function callback(transId, eventCode, result) {
if (eventCode == 4) {
error({message:"Position unavailable", code:2});
} else {
//no timestamp of location given?
success( { timestamp:null,
coords: {
latitude: result.ReturnValue.Latitude,
longitude: result.ReturnValue.Longitude,
altitude: result.ReturnValue.Altitude,
heading: result.ReturnValue.Heading }
});
}
}
//location criteria
var criteria = new Object();
criteria.LocationInformationClass = "BasicLocationInformation";
//make the call
provider.ILocation.GetLocation(criteria,callback);
}
} else {
pub.getCurrentPosition = function(success, error, opts) {
pub.jsonp.fetch(ipGeolocationSrv,
function( p ){ success( { timestamp: p.timestamp,
coords: {
latitude: p.latitude,
longitude: p.longitude,
heading: p.heading
}
});});
}
provider = true;
}
}
catch (e){
if( typeof(console) != u ) console.log(e);
return false;
}
return provider!=null;
}
return pub;
}();
In Internet explorer works correctly for me, but when I try it on Google Chrome it shows me the location of another city near my region. I'd like to be able to solve it, and let me show my correct location in google chrome.
I noticed that in internet explorer it takes a few seconds more to load to visualize the location, perhaps in the google chrome lacks some pre-load cleaning or some compatibility.
In Internet Explorer it is right:
but in google chrome the location shows me wrong:
My objective is to be able to obtain my location with the map in an exact way in different browsers with javascript or some type code on the client side.
If anyone knows, of course, I appreciate your attention.

Related

How to save result from Google Place Autocomplete

Firstly I would like to let you guys know that I have already checked many stack overflow Q&As, but I couldn't get the right solution.
I made a rails app by following the youtube.
https://www.youtube.com/watch?v=UtgwdLiJ5hA&t
It worked well including markerCluster which didn't cover in that youtube.
However, what I tried to add was that each user has his or her own search result(only the last one), and after hitting search button the page will be redirected to the same page with queries which have information about autocompleted place.
I succeeded in redirecting the same page with queries, but it was too hard to make the same map object as the one just after autocompleting.
The closest answer was as below, but it didn't work perfectly because AutocompleteService didn't return the first prediction as the place I wanted even though I put the exact address chosen just before redirecting.
How to set a default value for a Google places API auto complete textbox
The second trial was just copying some part of autocomplete object (bounds, location) and applying to the map object after redirecting. It seemed to work about only position, but the map display result has something wrong with boundary and the area seen.
The third trial was using place_id with the second trial, but I didn't think it would work.
I really wanted to insert the address text, select the address I chose before redirecting, and create autocomplete 'place_change' event AUTOMATICALLY as soon as the page was redirected. However, I have no idea how to do that.
Here is the main_map_controller.js (it is stimulus js)
import { Controller } from "stimulus"
export default class extends Controller {
// currentUrl is for redirecting to root_path in javascript
static targets = ["field", "map", "jsonMarkers", "currentUrl", "east", "north", "south", "west", "lat", "lng", "zoom"];
connect() {
if (typeof(google) != "undefined") {
this.initializeMap();
}
}
initializeMap() {
this._jason_locations = JSON.parse(this.jsonMarkersTarget.value);
this.map();
this.markerCluster();
this.autocomplete();
this.placeChanged();
// this.initialAutocomplete();
this.setPlace();
console.log('this.eastTarget.value:', this.eastTarget.value)
}
hasQuery() {
if (this.fieldTarget.value != "" && this.eastTarget.value != "" && this.northTarget.value != "" && this.southTarget.value != "" &&
this.westTarget.value != "" && this.latTarget.value != "" && this.lngTarget.value != "" && this.zoomTarget.value != ""
)
return true;
else
return false;
}
// Google map initialization
map() {
if (this._map == undefined) {
if (this.hasQuery())
{
this._map = new google.maps.Map(this.mapTarget, {
center: new google.maps.LatLng(
parseFloat(this.latTarget.value),
parseFloat(this.lngTarget.value)
),
zoom: 13
});
} else {
this._map = new google.maps.Map(this.mapTarget, {
center: new google.maps.LatLng(
0,
0
),
zoom: 13
});
}
// Try HTML5 geolocation
var cur_map = this._map;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
cur_map.setCenter({
lat: position.coords.latitude,
lng: position.coords.longitude
})
});
}
}
return this._map;
}
// markerCluster() make a group of markers
markerCluster() {
let current_map = this.map();
if (this._marker_cluster == undefined) {
var markers = this._jason_locations.map((location, i) => {
var marker = new google.maps.Marker({
position: {
lat: parseFloat(location["latitude"]),
lng: parseFloat(location["longitude"])
}
});
marker.addListener('click', () => {
let infoWindow = new google.maps.InfoWindow({
content: `<p>${location.address}</p>`
});
infoWindow.open(current_map, marker);
});
return marker;
});
this._marker_cluster = new MarkerClusterer(this.map(),
markers,
{imagePath: 'https://cdn.rawgit.com/googlemaps/js-marker-clusterer/gh-pages/images/m'}
);
}
return this._markers_cluster;
}
// Autocomplete function. It suggests the full address. 'formatted_address' was added to use user's bad behavior instead of
// using placeChanged(), but 'formatted_address' saved was not 100% same as the result address of autocomplete, so I didtn' use it.
// I don't understand why???
autocomplete() {
if (this._autocomplete == undefined) {
this._autocomplete = new google.maps.places.Autocomplete(this.fieldTarget);
this._autocomplete.bindTo('bounds', this.map());
this._autocomplete.setFields(['address_components', 'geometry', 'icon', 'name', 'formatted_address', 'place_id']);
this._autocomplete.addListener('place_changed', this.placeChanged.bind(this));
}
return this._autocomplete;
}
// If user typed strange word after autocomplete done, we should not allow to search with that word.
placeChanged() {
this._place_changed = this.fieldTarget.value;
}
// Because AutoComplete cannot have initial place, I had to use another class, AutocompleteService.
initialAutocomplete() {
if (this.fieldTarget.value == undefined || this.fieldTarget.value == "")
return;
let autocompleteService = new google.maps.places.AutocompleteService();
let request = { input: this.fieldTarget.value };
autocompleteService.getPlacePredictions(request, (predictionsArr, placesServiceStatus) => {
console.log('predictionArr:', predictionsArr);
console.log('placesServiceStatus:', placesServiceStatus);
let placeRequest = { placeId: predictionsArr[0].place_id };
let placeService = new google.maps.places.PlacesService(this.map());
placeService.getDetails(placeRequest, (placeResult, placeServiceStatus) => {
console.log('placeResult:', placeResult)
console.log('placeServiceStatus:', placeServiceStatus);
this.setPlace(placeResult);
});
});
}
// setPlace(placeResult) {
setPlace() {
// let place = this.autocomplete().getPlace();
// let place = placeResult;
if (!this.hasQuery()) {
return;
}
console.log('this.eastTarget.value:', this.eastTarget.value)
console.log('this.northTarget.value:', this.northTarget.value)
console.log('this.southTarget.value:', this.southTarget.value)
console.log('this.westTarget.value:', this.westTarget.value)
// let bound = {
// east: parseFloat(this.eastTarget.value),
// north: parseFloat(this.northTarget.value),
// south: parseFloat(this.southTarget.value),
// west: parseFloat(this.westTarget.value)
// }
// console.log('bounds:', bound)
// // this.map().fitBounds(place.geometry.viewport);
// // this.map().setCenter(place.geometry.location);
// this.map().fitBounds(bound);
// let bounds = this.map().getBounds();
// console.log('bounds:', bounds)
let bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(parseFloat(this.southTarget.value), parseFloat(this.westTarget.value)),
new google.maps.LatLng(parseFloat(this.northTarget.value), parseFloat(this.eastTarget.value))
);
this.map().fitBounds(bounds);
this.map().setCenter({
lat: parseFloat(this.latTarget.value),
lng: parseFloat(this.lngTarget.value)
});
let zoom = this.map().getZoom();
console.log('zoom:', zoom)
let center = this.map().getCenter();
console.log('center:', center)
document.getElementById("search-area").innerHTML = `Near ${this.fieldTarget.value}`;
this._jason_locations.forEach( location => {
var position = {
lat: parseFloat(location["latitude"]),
lng: parseFloat(location["longitude"])
}
console.log('position:', position)
if (bounds.contains(position)) {
document.getElementById(location["id"]).classList.remove("d-none")
} else {
document.getElementById(location["id"]).classList.add("d-none")
}
});
// this.latitudeTarget.value = place.geometry.location.lat();
// this.longitudeTarget.value = place.geometry.location.lng();
}
reloadMap() {
let place = this.autocomplete().getPlace();
console.log(place)
// this.setPlace(place);
if (place == undefined || this.fieldTarget.value == "" || this._place_changed != this.fieldTarget.value || !place.geometry) {
window.alert("Address is invalid!");
return;
}
this.map().fitBounds(place.geometry.viewport);
this.map().setCenter(place.geometry.location);
console.log('place.geometry.viewport:', place.geometry.viewport)
console.log('place.geometry.location:', place.geometry.location)
let bounds = this.map().getBounds();
console.log('bounds:', bounds)
let zoom = this.map().getZoom();
console.log('zoom:', zoom)
console.log('place.place_id:', place.place_id)
// This code was redirect root_path with query, but there was a problem that map was reloaded twice, so removed it.
// If adding query is not a solution for having each user's recent search history, then what else would it be?
let jsonParams = { "address": this.fieldTarget.value, ...bounds.toJSON(), ...place.geometry.location.toJSON(), "zoom": zoom.toString() };
const params = new URLSearchParams(jsonParams);
console.log(params.toString());
// Redirect to /posts/?address=xxxxx
console.log('params:', `${this.currentUrlTarget.value}/?${params.toString()}`);
window.location.href = `${this.currentUrlTarget.value}/?${params.toString()}`;
console.log('window.location.href:', window.location.href)
}
// prohibit Enter key, only allow to hit the search button.
preventSubmit(e) {
if (e.key == "Enter") {
e.preventDefault();
}
}
}
Yay, I finally figured it out by getting a hint from the following stack overflow site.
Google Maps map.getBounds() immediately after a call to map.fitBounds
What I fixed was modifying the second trial.
I didn't pass over the result of fitBounds() of autocomplete but viewport bounds of autocomplete itself, and after redirecting I wrapped the all codes after fitBounds() into the 'bound_changed' event handler with the help of the above solution.
Here is my fixed code, and it worked well. (Sorry about unused code and comment. I want to leave it for the record)
import { Controller } from "stimulus"
export default class extends Controller {
// currentUrl is for redirecting to root_path in javascript
static targets = ["field", "map", "jsonMarkers", "currentUrl", "east", "north", "south", "west", "lat", "lng"];
connect() {
if (typeof(google) != "undefined") {
this.initializeMap();
}
}
initializeMap() {
this._jason_locations = JSON.parse(this.jsonMarkersTarget.value);
this.map();
this.markerCluster();
this.autocomplete();
this.placeChanged();
// this.initialAutocomplete();
this.setPlace();
console.log('this.eastTarget.value:', this.eastTarget.value)
}
hasQuery() {
if (this.fieldTarget.value != "" && this.eastTarget.value != "" && this.northTarget.value != "" && this.southTarget.value != "" &&
this.westTarget.value != "" && this.latTarget.value != "" && this.lngTarget.value != ""
)
return true;
else
return false;
}
// Google map initialization
map() {
if (this._map == undefined) {
if (this.hasQuery())
{
this._map = new google.maps.Map(this.mapTarget, {
center: new google.maps.LatLng(
parseFloat(this.latTarget.value),
parseFloat(this.lngTarget.value)
)
// zoom: parseInt(this.zoomTarget.value)
});
} else {
this._map = new google.maps.Map(this.mapTarget, {
center: new google.maps.LatLng(
0,
0
),
zoom: 13
});
}
// Try HTML5 geolocation
var cur_map = this._map;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
cur_map.setCenter({
lat: position.coords.latitude,
lng: position.coords.longitude
})
});
}
}
return this._map;
}
// markerCluster() make a group of markers
markerCluster() {
let current_map = this.map();
if (this._marker_cluster == undefined) {
var markers = this._jason_locations.map((location, i) => {
var marker = new google.maps.Marker({
position: {
lat: parseFloat(location["latitude"]),
lng: parseFloat(location["longitude"])
}
});
marker.addListener('click', () => {
let infoWindow = new google.maps.InfoWindow({
content: `<p>${location.address}</p>`
});
infoWindow.open(current_map, marker);
});
return marker;
});
this._marker_cluster = new MarkerClusterer(this.map(),
markers,
{imagePath: 'https://cdn.rawgit.com/googlemaps/js-marker-clusterer/gh-pages/images/m'}
);
}
return this._markers_cluster;
}
// Autocomplete function. It suggests the full address. 'formatted_address' was added to use user's bad behavior instead of
// using placeChanged(), but 'formatted_address' saved was not 100% same as the result address of autocomplete, so I didtn' use it.
// I don't understand why???
autocomplete() {
if (this._autocomplete == undefined) {
this._autocomplete = new google.maps.places.Autocomplete(this.fieldTarget);
this._autocomplete.bindTo('bounds', this.map());
this._autocomplete.setFields(['address_components', 'geometry', 'icon', 'name']);
this._autocomplete.addListener('place_changed', this.placeChanged.bind(this));
}
return this._autocomplete;
}
// If user typed strange word after autocomplete done, we should not allow to search with that word.
placeChanged() {
this._place_changed = this.fieldTarget.value;
}
// Because AutoComplete cannot have initial place, I had to use another class, AutocompleteService.
initialAutocomplete() {
if (this.fieldTarget.value == undefined || this.fieldTarget.value == "")
return;
let autocompleteService = new google.maps.places.AutocompleteService();
let request = { input: this.fieldTarget.value };
autocompleteService.getPlacePredictions(request, (predictionsArr, placesServiceStatus) => {
console.log('predictionArr:', predictionsArr);
console.log('placesServiceStatus:', placesServiceStatus);
let placeRequest = { placeId: predictionsArr[0].place_id };
let placeService = new google.maps.places.PlacesService(this.map());
placeService.getDetails(placeRequest, (placeResult, placeServiceStatus) => {
console.log('placeResult:', placeResult)
console.log('placeServiceStatus:', placeServiceStatus);
this.setPlace(placeResult);
});
});
}
// setPlace(placeResult) {
setPlace() {
// let place = this.autocomplete().getPlace();
// let place = placeResult;
if (!this.hasQuery()) {
return;
}
console.log('this.eastTarget.value:', this.eastTarget.value)
console.log('this.northTarget.value:', this.northTarget.value)
console.log('this.southTarget.value:', this.southTarget.value)
console.log('this.westTarget.value:', this.westTarget.value)
// let bound = {
// east: parseFloat(this.eastTarget.value),
// north: parseFloat(this.northTarget.value),
// south: parseFloat(this.southTarget.value),
// west: parseFloat(this.westTarget.value)
// }
// console.log('bounds:', bound)
// // this.map().fitBounds(place.geometry.viewport);
// // this.map().setCenter(place.geometry.location);
// this.map().fitBounds(bound);
// let bounds = this.map().getBounds();
// console.log('bounds:', bounds)
let bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(parseFloat(this.southTarget.value), parseFloat(this.westTarget.value)),
new google.maps.LatLng(parseFloat(this.northTarget.value), parseFloat(this.eastTarget.value))
);
this.map().fitBounds(bounds);
google.maps.event.addListenerOnce(this.map(), 'bounds_changed', () => {
this.map().setCenter({
lat: parseFloat(this.latTarget.value),
lng: parseFloat(this.lngTarget.value)
});
bounds = this.map().getBounds();
console.log('bounds:', bounds)
let zoom = this.map().getZoom();
console.log('zoom:', zoom)
let center = this.map().getCenter();
console.log('center:', center)
document.getElementById("search-area").innerHTML = `Near ${this.fieldTarget.value}`;
this._jason_locations.forEach( location => {
var position = {
lat: parseFloat(location["latitude"]),
lng: parseFloat(location["longitude"])
}
console.log('position:', position)
if (bounds.contains(position)) {
document.getElementById(location["id"]).classList.remove("d-none")
} else {
document.getElementById(location["id"]).classList.add("d-none")
}
});
// this.latitudeTarget.value = place.geometry.location.lat();
// this.longitudeTarget.value = place.geometry.location.lng();
})
}
reloadMap() {
let place = this.autocomplete().getPlace();
console.log(place)
// this.setPlace(place);
if (place == undefined || this.fieldTarget.value == "" || this._place_changed != this.fieldTarget.value || !place.geometry) {
window.alert("Address is invalid!");
return;
}
// This code was redirect root_path with query, but there was a problem that map was reloaded twice, so removed it.
// If adding query is not a solution for having each user's recent search history, then what else would it be?
// let jsonParams = { "address": this.fieldTarget.value, ...bounds.toJSON(), ...place.geometry.location.toJSON(), "zoom": zoom.toString() };
let jsonParams = { "address": this.fieldTarget.value, ...place.geometry.viewport.toJSON(), ...place.geometry.location.toJSON()};
const params = new URLSearchParams(jsonParams);
// Redirect to /posts/?address=xxxxx
window.location.href = `${this.currentUrlTarget.value}/?${params.toString()}`;
}
// prohibit Enter key, only allow to hit the search button.
preventSubmit(e) {
if (e.key == "Enter") {
e.preventDefault();
}
}
}

Get Variables from Qlik Sense to JavaScript

I'm new with JS and I have this extension from Qlik Sense that I'm trying to change, I need to point some pins according to a variable. If value of variable $type is 'A' I use some pin, if value is 'B' another and so on. But I really don't know how this extension get values from QS. Any help please?
Follow the JS:
require.config({
paths: {
async: '/extensions/GoogleMaps-Sense/lib/async',
markerclusterer: '/extensions/GoogleMaps-Sense/lib/markerclusterer'
},
shim: {
'markerclusterer': {
exports: 'MarkerClusterer'
}
}
});
define(['qlik', './src/properties', './src/styles', 'markerclusterer', './src/abbreviateNumber', 'qvangular', 'async!https://maps.googleapis.com/maps/api/js?key=AIzaSyASz5bdD789VzsLyki1JCKhSnCd5pEPY3Q'], function(qlik, properties, styles, MarkerClusterer, abbreviateNumber, qv) {
var BASE_URL = '/extensions/GoogleMaps-Sense/';
if (typeof(Number.prototype.toRad) === "undefined") {
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
}
if (typeof(Number.prototype.toDeg) === "undefined") {
Number.prototype.toDeg = function() {
return this * 180 / Math.PI;
}
}
return {
initialProperties: {
version: 1,
qHyperCubeDef: {
qSuppressZero: true,
qSuppressMissing: true
},
gmaps: {
cluster: {
oneStyle: false,
maxZoom: 10
},
map: {
mode: 'cluster',
customIcon: null,
iconUrl: '',
maxZoom: 18,
style: 'default'
}
}
},
definition: properties,
snapshot: {
canTakeSnapshot: true
},
paint: function($element, layout) {
$element.empty();
this.backendApi.cacheCube.enabled = false;
var _this = this;
var markers = [];
var selectedMarkers = [];
var rectangles = [];
var selectedRects = [];
var columns = layout.qHyperCube.qSize.qcx;
var totalheight = layout.qHyperCube.qSize.qcy;
var pageheight = Math.floor(10000 / columns);
var numberOfPages = Math.ceil(totalheight / pageheight);
var Promise = qv.getService('$q');
var promises = Array.apply(null, Array(numberOfPages)).map(function(data, index) {
var page = {
qTop: (pageheight * index) + index,
qLeft: 0,
qWidth: columns,
qHeight: pageheight
};
return this.backendApi.getData([page]);
}, this)
Promise.all(promises).then(function(data) {
render(data);
});
function render(data) {
var useCustomStyle = layout.gmaps.map.style !== 'default';
var hasMeasure = layout.qHyperCube.qMeasureInfo.length >= 1 ? true : false;
var hasPopup = layout.qHyperCube.qMeasureInfo.length === 2 ? true : false;
//The bounds object, used to determain which part of the map to show based on data
var bounds = new google.maps.LatLngBounds();
var mapOptions = {
maxZoom: layout.gmaps.map.maxZoom,
panControl: true,
zoomControl: true,
overviewMapControl: false,
overviewMapControlOptions: {
opened: false
},
scaleControl: false,
streetViewControl: true,
mapTypeControlOptions: {
mapTypeIds: [google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.TERRAIN, google.maps.MapTypeId.HYBRID, 'map_style']
}
};
//Put the map on the page so give some visual feedback
var map = new google.maps.Map($element.get(0), mapOptions);
if (useCustomStyle) {
var selectedStyle = styles.filter(function(d) {
return d.key === layout.gmaps.map.style
});
var styledMap = new google.maps.StyledMapType(selectedStyle[0].data, {
name: layout.gmaps.map.style
});
map.mapTypes.set('map_style', styledMap);
map.setMapTypeId('map_style');
};
//Create a marker for each row of data
data.forEach(function(obj) {
obj[0].qMatrix.forEach(function(row, index) {
if (row[0].qText == '-') return;
//Parse the dimension
var latlng = JSON.parse(row[0].qText);
//Reverse the order as QS sends long lat
var point = new google.maps.LatLng(latlng[1], latlng[0]);
//Create our marker - if we have a expression then use that otherwise default to just show locations
var image = 'https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png';
var marker = new google.maps.Marker({
position: point,
title: '',
icon: image,
customData: hasMeasure ? row[1].qText : 1,
qElem: row[0].qElemNumber
});
//If we have popup values for each marker create the popup windows
if (hasPopup) {
marker.infoWindow = new google.maps.InfoWindow({
content: row[2].qText
});
google.maps.event.addListener(marker, 'mouseover', function() {
this.infoWindow.open(map, this);
});
google.maps.event.addListener(marker, 'mouseout', function() {
this.infoWindow.close();
});
};
//Add click handler
google.maps.event.addListener(marker, 'click', (function(value) {
return function() {
_this.selectValues(0, [value], true);
highlightMarkers(value)
}
})(row[0].qElemNumber));
bounds.extend(point);
markers.push(marker);
});
});
//Fit map to bounds
map.fitBounds(bounds);
//Clustering enabled
if (layout.gmaps.map.mode === 'cluster') {
if (layout.gmaps.cluster.oneStyle) {
var clusterStyles = [{
opt_textColor: 'black',
url: BASE_URL + 'images/singlecluster.png',
height: 56,
width: 55
}];
};
var mcOptions = {
imagePath: BASE_URL + 'images/m',
styles: clusterStyles,
maxZoom: layout.gmaps.cluster.maxZoom
};
//Draw clusters onto map
var markerCluster = new MarkerClusterer(map, markers, mcOptions);
markerCluster.setCalculator(function(markers, clusterStyles) {
var index = 0,
count = markers.length,
total = count;
while (total !== 0) {
//Create a new total by dividing by a set number
total = parseInt(total / 5, 10);
//Increase the index and move up to the next style
index++;
}
index = Math.min(index, clusterStyles);
var measure = 0;
for (var i = 0, k = count; i < k; i++) {
measure += parseInt(markers[i].customData)
}
var abbreviatedValue = abbreviateNumber(measure)
return {
text: abbreviatedValue,
index: index
};
});
};
if (layout.gmaps.map.mode === 'marker') {
markers.forEach(function(d) {
d.setMap(map);
})
};
if (layout.gmaps.map.mode === 'boxes') {
markers.forEach(function(d) {
var distance = d.customData > 1 ? d.customData : 10;
var lat = d.position.lat();
var lng = d.position.lng();
var boxbounds = new google.maps.LatLngBounds(box(lat, lng, 225, distance), box(lat, lng, 45, distance))
var rect = new google.maps.Rectangle({
strokeColor: layout.gmaps.boxes.strokeFill,
strokeOpacity: +layout.gmaps.boxes.strokeOpacity,
strokeWeight: +layout.gmaps.boxes.strokeWeight,
fillColor: layout.gmaps.boxes.fillColor,
fillOpacity: +layout.gmaps.boxes.fillOpacity,
qElem: d.qElem,
map: map,
bounds: boxbounds
});
//Add click handler
google.maps.event.addListener(rect, 'click', (function(value) {
return function() {
_this.selectValues(0, [value], true);
highlightRects(value)
}
})(d.qElem));
rectangles.push(rect);
})
};
};
//In selection mode - loop over markers to highlight markers scheduled for selection.
function highlightMarkers(qElem) {
var idx = selectedMarkers.indexOf(qElem);
if (idx > -1) {
selectedMarkers.splice(idx, 1)
} else {
selectedMarkers.push(qElem)
}
markers.forEach(function(marker) {
if (selectedMarkers.indexOf(marker.qElem) === -1) {
marker.setOpacity(0.5)
} else {
marker.setOpacity(1);
}
});
};
//In selection mode - loop over markers to highlight markers scheduled for selection.
function highlightRects(qElem) {
var idx = selectedRects.indexOf(qElem);
if (idx > -1) {
selectedRects.splice(idx, 1)
} else {
selectedRects.push(qElem)
}
rectangles.forEach(function(marker) {
if (selectedRects.indexOf(marker.qElem) === -1) {
marker.setOptions({
fillOpacity: +layout.gmaps.boxes.fillOpacity / 2,
strokeOpacity: +layout.gmaps.boxes.strokeOpacity / 2
})
} else {
marker.setOptions({
fillOpacity: +layout.gmaps.boxes.fillOpacity,
strokeOpacity: +layout.gmaps.boxes.strokeOpacity
})
}
});
};
function box(lat, lng, brng, dist) {
this._radius = 6371;
var dist = dist / this._radius;
var brng = brng.toRad();
var lat1 = lat.toRad();
var lon1 = lng.toRad();
var lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) +
Math.cos(lat1) * Math.sin(dist) *
Math.cos(brng));
var lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) *
Math.cos(lat1), Math.cos(dist) -
Math.sin(lat1) * Math.sin(lat2));
lon2 = (lon2 + 3 * Math.PI) % (2 * Math.PI) - Math.PI;
return new google.maps.LatLng(lat2.toDeg(), lon2.toDeg());
}
}
};
});
I think this might help
/**
* Retrieve the values of a list of variables.
*
* Since $q.all fails on the first error, we have to resolve all first
*
* #param {string[]} `varList` - The variable names.
* #param {object} `app` - The (Qlik Sense) app.
*
* #returns {Promise}
*
* #api public
*/
this.getEngineVarListValues = function ( app, varList ) {
if ( varList && Array.isArray( varList ) ) {
var promises = [];
varList.forEach( function ( variable ) {
promises.push( self.getEngineVarValue( app, variable ) )
} );
return $q.all( promises );
}
return $q.reject( new Error( 'getEngineVarListValues variable list passed.' ) );
};
Taken from https://github.com/stefanwalther/sense-extension-utils/blob/master/src/variable-utils.js
var app = qlik.currApp();
//get the variable content
app.variable.getContent('MYVAR',function ( reply ){
alert( JSON.stringify( reply ) );
});
source: http://help.qlik.com/en-US/sense-developer/June2017/Subsystems/APIs/Content/CapabilityAPIs/qlik-variable-interface.htm

Google maps API V3 method fitBounds() using Prototypejs

I have a div as follows to display a google map:
#map {
width: 300px;
height: 300px;
border: 1px solid #DDD;
}
<div id="map"></div>
I want to display the map with a zoom level that fits the bounds of the above viewport.
When I code as follows it works fine:
var geocoder = new google.maps.Geocoder();
var map = new google.maps.Map($('#map')[0], {zoom: 10});
geocoder.geocode({ 'address': generatedAddress }, function (results, status) {
if (status == 'OK') {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
if (results[0].geometry.viewport)
map.fitBounds(results[0].geometry.viewport);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
When I use typeahead-addresspicker.js to generate the map it zooms in too far?
I've narrowed it down to the following code. When you call the AddressPicker.prototype.updateMap function the boundsForLocation option on AddressPicker.prototype.initMap function should return this.map.fitBounds(response.geometry.viewport); When I debug I can see that it is hitting the following code inside the AddressPicker.prototype.updateBoundsForPlace function as expected:
if (response.geometry.viewport) {
console.log('test');
return this.map.fitBounds(response.geometry.viewport);
}
What I don't understand is how it gets wired back to the google.maps.Map - I'm not familiar with ptototypejs? So basically running through it, we initilize the map by calling initMap, then we call the updateMap function. Inside updateMap function we are calling the following snippet of code:
if (_this.map) {
if ((_ref = _this.mapOptions) != null) {
_ref.boundsForLocation(response);
}
}
which is suppose to set the bounds by calling the updateBoundsForPlace but the google maps options doesnt expose any property called boundsForLocation?
AddressPicker.prototype.initMap = function() {
var markerOptions, _ref, _ref1;
if ((_ref = this.options) != null ? (_ref1 = _ref.map) != null ? _ref1.gmap : void 0 : void 0) {
this.map = this.options.map.gmap;
} else {
this.mapOptions = $.extend({
zoom: 3,
center: new google.maps.LatLng(0, 0),
mapTypeId: google.maps.MapTypeId.ROADMAP,
boundsForLocation: this.updateBoundsForPlace
}, this.options.map);
this.map = new google.maps.Map($(this.mapOptions.id)[0], this.mapOptions);
}
this.lastResult = null;
markerOptions = $.extend({
draggable: true,
visible: false,
position: this.map.getCenter(),
map: this.map
}, this.options.marker || {});
this.marker = new google.maps.Marker(markerOptions);
if (markerOptions.draggable) {
return google.maps.event.addListener(this.marker, 'dragend', this.markerDragged);
}
};
AddressPicker.prototype.updateMap = function(event, place) {
if (this.options.placeDetails) {
return this.placeService.getDetails(place, (function(_this) {
return function(response) {
var _ref;
_this.lastResult = new AddressPickerResult(response);
if (_this.marker) {
_this.marker.setPosition(response.geometry.location);
_this.marker.setVisible(true);
}
if (_this.map) {
if ((_ref = _this.mapOptions) != null) {
_ref.boundsForLocation(response);
}
}
return $(_this).trigger('addresspicker:selected', _this.lastResult);
};
})(this));
} else {
return $(this).trigger('addresspicker:selected', place);
}
};
AddressPicker.prototype.updateBoundsForPlace = function(response) {
if (response.geometry.viewport) {
return this.map.fitBounds(response.geometry.viewport);
} else {
this.map.setCenter(response.geometry.location);
return this.map.setZoom(this.options.zoomForLocation);
}
};
Managed to fix by commenting out the following lines:
//if (response.geometry.viewport) {
// return this.map.fitBounds(response.geometry.viewport);
//} else {
this.map.setCenter(response.geometry.location);
return this.map.setZoom(this.options.zoomForLocation);
//}

Removing selected geojson feature with Google Maps JavaScript API

I'm using the Google Maps Javascript API to let users draw custom polygons with properties to be entered into a database. Before inserting them into the database though, they need to be able to delete selected shapes they've drawn.
This function isn't throwing any errors but it also isn't deleting the feature. What am I doing wrong?
var selectedshape;
function initMap() {
map = new google.maps.Map(document.getElementById('map2'), {
zoom: 1,
center: { lat: -1, lng: 1 }
});
function clearSelection() {
if (selectedShape) {
selectedShape = null;
}
}
function setSelection(shape) {
clearSelection();
selectedShape = shape;
}
map.data.addListener('click', function(event) {
map.controls[google.maps.ControlPosition.TOP_RIGHT].clear()
setSelection(event.feature);
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(centerControlDiv);
map.data.revertStyle();
map.data.overrideStyle(event.feature, { strokeWeight: 8 });
selectID = event.feature.getProperty('uniqid')
selectID = event.feature.getProperty('uniqgeom')
$(".getSelectID").attr("id", selectID)
});
bounds = new google.maps.LatLngBounds();
map.data.addListener('addfeature', function(event) {
processPoints(event.feature.getGeometry(), bounds.extend, bounds);
map.setCenter(bounds.getCenter());
map.fitBounds(bounds);
var uniqid = "_" + Date.now();
feature_type = event.feature.getGeometry().getType()
if (feature_type == 'LineString') {
encoded_geom = event.feature.getProperty('uniqgeom') || google.maps.geometry.encoding.encodePath(event.feature.getGeometry().getArray());
} else {
encoded_geom = event.feature.getProperty('uniqgeom') || google.maps.geometry.encoding.encodePath(event.feature.getGeometry().getArray()[0].getArray())
}
event.feature.setProperty('encoded_geom', encoded_geom);
selectID = encoded_geom
$(".getSelectID").attr("id", selectID)
event.feature.setProperty('uniqid', uniqid);
});
function deleteSelectedShape() {
map.controls[google.maps.ControlPosition.TOP_RIGHT].clear()
if (selectedShape) {
map.data.forEach(function(feature) {
if (feature.getProperty('uniqid') == selectedShape.uniqid) {
map.data.remove(feature);
}
});
}
}
I believe the problem is a syntax error in
if (feature.getProperty('uniqid') == selectedShape.uniqid) {

JQuery: collection array length being capped at 100

I'm using Splunk Web Framework and Google Maps app to create a custom map implementation. The problem i'm seeing is when I send splunk search results information into the google maps js it caps my rows at 100. Can someone take a look at the code below and see if there any anywhere that might cause an array to be capped at 100?
/** #license
* RequireJS plugin for async dependency load like JSONP and Google Maps
* Author: Miller Medeiros
* Version: 0.1.1 (2011/11/17)
* Released under the MIT license
*/
define('async',[],function(){
var DEFAULT_PARAM_NAME = 'callback',
_uid = 0;
function injectScript(src){
var s, t;
s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = src;
t = document.getElementsByTagName('script')[0]; t.parentNode.insertBefore(s,t);
}
function formatUrl(name, id){
var paramRegex = /!(.+)/,
url = name.replace(paramRegex, ''),
param = (paramRegex.test(name))? name.replace(/.+!/, '') : DEFAULT_PARAM_NAME;
url += (url.indexOf('?') < 0)? '?' : '&';
return url + param +'='+ id;
}
function uid() {
_uid += 1;
return '__async_req_'+ _uid +'__';
}
return{
load : function(name, req, onLoad, config){
if(config.isBuild){
onLoad(null); //avoid errors on the optimizer
}else{
var id = uid();
window[id] = onLoad; //create a global variable that stores onLoad so callback function can define new module after async load
injectScript(formatUrl(name, id));
}
}
};
});
requirejs.s.contexts._.nextTick = function(f){f()}; require(['css'], function(css) { css.addBuffer('splunkjs/css/googlemap.css'); }); requirejs.s.contexts._.nextTick = requirejs.nextTick;
define('splunkjs/mvc/googlemapview',['require','exports','module','underscore','./mvc','./basesplunkview','./messages','async!http://maps.googleapis.com/maps/api/js?sensor=false','css!../css/googlemap.css'],function(require, exports, module) {
var _ = require('underscore');
var mvc = require('./mvc');
var BaseSplunkView = require("./basesplunkview");
var Messages = require("./messages");
require("async!http://maps.googleapis.com/maps/api/js?sensor=false");
require("css!../css/googlemap.css");
var GoogleMapView = BaseSplunkView.extend({
moduleId: module.id,
className: "splunk-googlemap",
options: {
managerid: null,
data: "preview"
},
initialize: function() {
this.configure();
this.bindToComponentSetting('managerid', this._onManagerChange, this);
this.map = null;
this.markers = [];
// If we don't have a manager by this point, then we're going to
// kick the manager change machinery so that it does whatever is
// necessary when no manager is present.
if (!this.manager) {
this._onManagerChange(mvc.Components, null);
}
},
_onManagerChange: function(managers, manager) {
if (this.manager) {
this.manager.off(null, null, this);
this.manager = nul=]=]l;
}
=]== if (this.resultsModel) {
= this.resultsModel.off(null, null, this);
this.resultsModel.destroy();
this.resultsModel = null;
}
if (!manager) {
this.message('no-search');
return;
}
// Clear any messages, since we have a new manager.
this.message("empty");
this.manager = manager;
this.resultsModel = manager.data(this.settings.get("data"), {
output_mode: "json_rows"
});
manager.on("search:start", this._onSearchStart, this);
manager.on("search:progress", this._onSearchProgress, this);
manager.on("search:cancelled", this._onSearchCancelled, this);
manager.on("search:error", this._onSearchError, this);
this.resultsModel.on("data", this.render, this);
this.resultsModel.on("error", this._onSearchError, this);
manager.replayLastSearchEvent(this);
},
_onSearchCancelled: function() {
this._isJobDone = false;
this.message('cancelled');
},
_onSearchError: function(message, err) {
this._isJobDone = false;
var msg = message;
if (err && err.data && err.data.messages && err.data.messages.length) {
msg = _(err.data.messages).pluck('text').join('; ');
}
this.message({
level: "error",
icon: "warning-sign",
message: msg
});
},
_onSearchProgress: function(properties) {
properties = properties || {};
var content = properties.content || {};
var previewCount = content.resultPreviewCount || 0;
var isJobDone = this._isJobDone = content.isDone || false;
if (previewCount === 0 && isJobDone) {
this.message('no-results');
return;
}
if (previewCount === 0) {
this.message('waiting');
return;
}
},
_onSearchStart: function() {
this._isJobDone = false;
this.message('waiting');
},
clearMarkers: function() {
var count = this.markers.length;
for (var i = 0; i < count; ++i)
this.markers[i].setMap(null);
this.markers.length = 0;
},
createMap: function() {
this.map = new google.maps.Map(this.el, {
center: new google.maps.LatLng(47.60, -122.32),
zoom: 2,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
this.map.setOptions(this.options);
},
message: function(info) {
this.map = null;
Messages.render(info, this.$el);
},
render: function() {
if (!this.manager) {
return;
}
if (!this.resultsModel || !this.resultsModel.hasData()) {
if (this.resultsModel && !this.resultsModel.hasData() && this._isJobDone) {
this.message("no-results");
}
return this;
}
if (!this.map) {
this.createMap();
}
var that = this;
this.clearMarkers();
this.resultsModel.collection().each(function(row) {
var lat = parseFloat(row.get("lat"));
var lng = parseFloat(row.get("lng"));
var latlng = new google.maps.LatLng(lat, lng);
var marker = new google.maps.Marker({
position: latlng,
map: that.map
});
that.markers.push(marker);
});
return this;
}
});
return GoogleMapView;
});
requirejs.s.contexts._.nextTick = function(f){f()}; require(['css'], function(css) { css.setBuffer('/* */\n\n/* Bootstrap Css Map Fix*/\n.splunk-googlemap img { \n max-width: none;\n}\n/* Bootstrap Css Map Fix*/\n.splunk-googlemap label { \n width: auto; \n display:inline; \n} \n/* Set a small height on the map so that it shows up*/\n.splunk-googlemap {\n min-height: 100px;\n height: 100%;\n}\n'); }); requirejs.s.contexts._.nextTick = requirejs.nextTick;
From a quick search it seems it could be splunk capping at 100?
See http://answers.splunk.com/answers/52782/100-result-limit-in-js-sdk.html

Categories

Resources