I want to send coordinates to a user's google maps with waypoints. Unfortunately, it is only sending the starting point and destination. I need it to work for all devices regardless of their last update, if possible. The goal is for the user to be able to add up to 4 waypoints or none at all and the code to work normally. I also looked into node modules, but was unable to find any that met my needs. I am open to all suggestions.
`const rideWithGoogle = () => {
console.log("currentDestinationCords: ", currentDestinationCords)
console.log("currentLocation: ", currentLocation)
console.log("Ride with Google: ", waypointString)
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
// Open Google Maps with coordinates on iOS
//window.location.href = `comgooglemaps://?daddr=${encodedPolyline}`;
//window.location.href = `comgooglemaps://?q=${currentLocation?.lat}%2C${currentLocation?.lng}&waypoints=${waypointString}&daddr=${currentDestinationCords[0]}%2C${currentDestinationCords[1]}`;
window.location.href = `comgooglemaps://?saddr=${currentLocation?.lat}%2C${currentLocation?.lng}&daddr=${currentDestinationCords[0]}%2C${currentDestinationCords[1]}&waypoints=via:${waypointString}`
//window.location.href = `comgooglemapsurl://www.google.com/maps/dir/${currentLocation?.lat},${currentLocation?.lng}/${waypointString}/${currentDestinationCords[0]},${currentDestinationCords[1]}`
} else {
if (navigator.getInstalledRelatedApps) {
navigator.getInstalledRelatedApps().then(relatedApps => {
if (relatedApps.some(app => app.platform === "play" && app.id === "com.google.android.apps.maps")) {
// Google Maps is installed, so launch it with the coordinates
navigator.launchApp("com.google.android.apps.maps", `geo:0,0?q=${currentLocation?.lat}%2C${currentLocation?.lng}&waypoints=${waypointString}&daddr=${currentDestinationCords[0]}%2C${currentDestinationCords[1]}`).then(() => {
console.log("Google Maps launched successfully!");
}).catch(err => {
console.log("Error launching Google Maps: ", err);
});
} else {
console.log("Google Maps is not installed on this device.");
}
});
}
}
}
const go = () => {
console.log("waypoint: ", waypoint)
if (waypoint?.length < 1) {
{!riderDidPay && setPaymentOption(true)};
if (riderDidPay) {
if (waypoint.length > 0) {
let wps = "";
for (let i = 0; i < waypoint.length; i++) {
wps += `${waypoint[i]?.lat}%2C${waypoint[i]?.lng}|`;
}
setWaypointString(wps.slice(0, -1));
}
}
} else {
// setIsUserDriving(!isUserDriving);
// map?.panTo(currentLocation);
// map?.setZoom(20);
if (waypoint?.length > 0) {
let wps = "";
for (let i = 0; i < waypoint.length; i++) {
wps += `${waypoint[i]?.lat}%2C${waypoint[i]?.lng}|`;
}
setWaypointString(wps.slice(0, -1));
setReadyToDrive(true);
}
setReadyToDrive(true);
}
}`
Related
Im trying to implement the XLS Extension. In the ModelData class, i cannot get objects leaf nodes because the viewer is undefined.
Here is the problematic method:
getAllLeafComponents(callback) {
// from https://learnforge.autodesk.io/#/viewer/extensions/panel?id=enumerate-leaf-nodes
viewer.getObjectTree(function (tree) {
let leaves = [];
tree.enumNodeChildren(tree.getRootId(), function (dbId) {
if (tree.getChildCount(dbId) === 0) {
leaves.push(dbId);
}
}, true);
callback(leaves);
});
}
Im getting Cannot read properties of undefined (reading 'getObjectTree') , meaning viewer is undefined.
However, viewer is working and displaying documents.
I tried to call it by window.viewer and this.viewer to no avail.
Thanks in advance for any help
It looks like it missed two lines. Could you try the revised one below?
// Model data in format for charts
class ModelData {
constructor(viewer) {
this._modelData = {};
this._viewer = viewer;
}
init(callback) {
var _this = this;
var viewer = _this._viewer;
_this.getAllLeafComponents(function (dbIds) {
var count = dbIds.length;
dbIds.forEach(function (dbId) {
viewer.getProperties(dbId, function (props) {
props.properties.forEach(function (prop) {
if (!isNaN(prop.displayValue)) return; // let's not categorize properties that store numbers
// some adjustments for revit:
prop.displayValue = prop.displayValue.replace('Revit ', ''); // remove this Revit prefix
if (prop.displayValue.indexOf('<') == 0) return; // skip categories that start with <
// ok, now let's organize the data into this hash table
if (_this._modelData[prop.displayName] == null) _this._modelData[prop.displayName] = {};
if (_this._modelData[prop.displayName][prop.displayValue] == null) _this._modelData[prop.displayName][prop.displayValue] = [];
_this._modelData[prop.displayName][prop.displayValue].push(dbId);
})
if ((--count) == 0) callback();
});
})
})
}
getAllLeafComponents(callback) {
var _this = this;
var viewer = _this._viewer;
// from https://learnforge.autodesk.io/#/viewer/extensions/panel?id=enumerate-leaf-nodes
viewer.getObjectTree(function (tree) {
var leaves = [];
tree.enumNodeChildren(tree.getRootId(), function (dbId) {
if (tree.getChildCount(dbId) === 0) {
leaves.push(dbId);
}
}, true);
callback(leaves);
});
}
hasProperty(propertyName){
return (this._modelData[propertyName] !== undefined);
}
getLabels(propertyName) {
return Object.keys(this._modelData[propertyName]);
}
getCountInstances(propertyName) {
return Object.keys(this._modelData[propertyName]).map(key => this._modelData[propertyName][key].length);
}
getIds(propertyName, propertyValue) {
return this._modelData[propertyName][propertyValue];
}
}
I've set up a project where Im limiting the API response to 5, and upon scrolling to the bottom o the page, I make a new API call to fetch the next 2 items in the API. But with the current code it only checks if the 5 items previously fetched exists in the cards state. Im quite unsure as to how to go about fetching the 2 next items in the API? Does anyone have any suggestions as to how to go about this? Thanks,
var app = new Vue({
el: '#app',
data: {
cards: []
},
methods: {
scroll(card) {
window.onscroll = () => {
let bottomOfWindow = document.documentElement.scrollTop +
window.innerHeight === document.documentElement.offsetHeight;
if(bottomOfWindow) {
const url =
'https://api.jsonbin.io/b/5cab36508b8d1301a25bd8fa/1/';
axios.get(url)
.then(response => {
for (var i = 0; i < this.cards.length; i++) {
console.log('Cards id: ', this.cards[i].id)
if(this.cards[i].id !==
response.data.results[i].id){
for (var x = 0; x < 2; x++) {
this.cards.push(response.data.results[x])
}
} else{
console.log('No more cards to load')
}
}
}
})
}
}
},
getAPI(){
const url = 'https://api.jsonbin.io/b/5cab36508b8d1301a25bd8fa/1/';
axios.get(url)
.then(response => {
for (var i = 0; i < 5; i++) {
this.cards.push(response.data.results[i]);
}
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});
console.log(this.cards)
}
},
mounted() {
this.scroll(this.card)
}
})
Changed the method in which you do the checking. Instead of doing it from cards length you loop through the results length and once you reach a card that doesnt exist you add them, keep track of the amount added and return after 2 or when there is none left. I changed the loop logic to so.
//Card with position i from results doesn't exist
if(this.cards[i] == undefined){
//add this card - maybe add more logic to check for duplicate incase of reordering of response
this.cards.push(response.data.results[i])
//track card added
cardsAdded++;
} else {
console.log('No more cards to load')
}
//check if cards added has reach limit of 2
if(cardsAdded == 2)
return;
See: https://jsfiddle.net/as4dm03q/
I have custom code to create a nearby search of places on google map.
Each search type creates a new layer, removed when selecting a different search type, my problem is, even thought he layer is removed, here in Thailand we have "Google partners advertising" show dependant on the search type and this "Layer" doesnt get removed, but added to when creating a new search layer.
This is the code I use to create the search (in part):
Creating a layer (Google):
<div id="map_layers_google">
<input type="checkbox" name="map_google" id="map_google_restaurant" class="box" onclick="Propertywise.Maps.getDataWithinBounds('google_restaurant');" value="google_restaurant">
</div>
getDataWithinBounds: function(layer_name, except_this_area) {
if (!Propertywise.Design.is_ie8_or_less) {
this.layers_on_map[layer_name] = true;
this.getEntitiesWithinBounds(layer_name);
}
getEntitiesWithinBounds: function(entity_name) {
var $this = this;
if (!this.getBounds()) {
setTimeout(function() {
$this.getEntitiesWithinBounds(entity_name);
}, 20);
} else {
var layer_name, category;
var $this_input_el = jQuery("#map_" + entity_name);
jQuery("#map_updating").fadeIn('fast');
if (entity_name.indexOf('google') != -1) {
layer_name = "google";
category = entity_name.replace("google_", "");
} else if (entity_name.indexOf('school') != -1) {
layer_name = "schools";
category = entity_name.replace("schools_", "");
} else if (entity_name.indexOf('events') != -1) {
layer_name = "events";
category = entity_name.replace("events_", "");
} else {
layer_name = "transport";
this.toggleTransitLayer();
}
jQuery("#map_layers_" + layer_name + " input").each(function(index, value) {
var el_id = jQuery(this).attr("id");
var el_entity_name = el_id.replace("map_", "");
Propertywise.Maps.layers_on_map[el_entity_name] = false;
if (jQuery(this).is(":checked") && el_entity_name != entity_name) {
jQuery(this).attr("checked", false);
}
if (jQuery(this).is(":checked") && el_entity_name == entity_name) {
Propertywise.Maps.layers_on_map[entity_name] = true;
}
});
if (jQuery("#map_" + entity_name).is(':checked') || Propertywise.this_page == "school") {
if (layer_name == "google") {
infoWindow = new google.maps.InfoWindow();
Propertywise.Maps.removeMarkers(layer_name);
var request = {
bounds: Propertywise.Maps.map.getBounds(),
types: [category]
};
service = new google.maps.places.PlacesService(Propertywise.Maps.map);
service.radarSearch(request, function(results, status) {
jQuery("#map_updating").fadeOut('fast');
if (status != google.maps.places.PlacesServiceStatus.OK) {
return;
}
for (var i = 0, result; result = results[i]; i++) {
Propertywise.Maps.createMarker(result.geometry.location.lat(), result.geometry.location.lng(), {
place: result,
type: category
});
}
});
}
} else {
this.removeMarkers(layer_name);
jQuery("#map_updating").fadeOut('fast');
}
}
}
And this is the setup and remove each layer:
setUpLayers: function() {
var $this = this;
jQuery.each(this.layers, function(layer_name, value) {
Propertywise.Ajax.requests[layer_name] = [];
$this.layers[layer_name] = [];
});
},
removeMarkers: function(layer_name) {
if (Propertywise.Maps.map) {
var layer = this.layers[layer_name];
for (var i = 0; i < layer.length; i++) {
layer[i].setMap(null);
}
layer = [];
}
}
Here is link to screen shot of the problem.
screenshot
Question is, can anyone help with either changing the above to remove the complete layer(not just marker layer) or advise how to remove the advertising.. I understand this is part of terms of Google to display, but its unprofessional and looks terrible.
Best
Malisa
how could I enable camera selection on primefaces photocam ?
Here is what I have done presently without luck ( image not rendering... )
<pm:content>
<script>
jQuery(document).ready(function() {
'use strict';
var videoElement = document.querySelector('video');
var videoSelect = document.querySelector('select#videoSource');
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
function gotSources(sourceInfos) {
for (var i = 0; i !== sourceInfos.length; ++i) {
var sourceInfo = sourceInfos[i];
var option = document.createElement('option');
option.value = sourceInfo.id;
if (sourceInfo.kind === 'audio') {
} else if (sourceInfo.kind === 'video') {
option.text = sourceInfo.label || 'camera ' + (videoSelect.length + 1);
videoSelect.appendChild(option);
} else {
console.log('Some other kind of source: ', sourceInfo);
}
}
}
if (typeof MediaStreamTrack === 'undefined' ||
typeof MediaStreamTrack.getSources === 'undefined') {
alert('This browser does not support MediaStreamTrack.\n\nTry Chrome.');
} else {
MediaStreamTrack.getSources(gotSources);
}
function successCallback(stream) {
window.stream = stream; // make stream available to console
videoElement.src = window.URL.createObjectURL(stream);
videoElement.play();
}
function errorCallback(error) {
console.log('navigator.getUserMedia error: ', error);
}
function start() {
videoElement = document.querySelector('video');
if (!!window.stream) {
videoElement.src = null;
window.stream.stop();
}
var videoSource = videoSelect.value;
var constraints = {
audio: false,
video: {
optional: [{
sourceId: videoSource
}]
}
};
navigator.getUserMedia(constraints, successCallback, errorCallback);
}
videoSelect.onchange = start;
start();
});
</script>
<p:outputLabel value="Seleccione Camara:" />
<select id="videoSource"></select>
<p:photoCam widgetVar="pc" listener="#{eventoMB.oncapture}" update="photo" />
I am trying to achieve this goal by using javascript but the problem something is preventing the change proposed here, which I could not identify up to know...
Thanks for your attention.
Well in case someone needs this information:
in attach function(c) after these lines ( around line 89 from primefaces-5.2.jar\META-INF\resources\primefaces\photocam\photocam.js ) :
b.style.transform = "scaleX(" + h + ") scaleY(" + g + ")"
}
c.appendChild(b);
I added the following lines:
var constraints = {
audio: false,
video: {
facingMode: {
exact: "environment"
}
}
};
this.video = b;
var i = this;
navigator.getUserMedia(constraints, function(j) {
Note that specifing facingMode for the video constraints apparently does the trick in firefox for android and google only in the desktop version apparently as stated here:
GetUserMedia - facingmode
By the way it would be interesting to me to discuss if this solution is the more appropiate thing to do or there is a better one.
Hope this helps someone else, thanks anyway.
I'm trying to split a big request for elevation into multiple requests to avoid the 1sec/request and 512 coords limit in each request.
The problem I face is that the reply of my requests are not always received in the good order. Is using setInterval reliable enough?
Here is an example of response received in the wrong order that cause a problem (before using setInterval):
https://www.dropbox.com/s/x00jdnprj6w7lga/correctMap.png?dl=0
Here is my latest code:
function getCourseElevationData() {
var path = bikePathCoordinates; //Bunch of lat,long coords
// numberRequestToDo = Math.ceil(path.length/512); //TODO: split request in multiple 512 pack (google quotas)
numberRequestToDo = 2; //Temporary for testing
currentRequestNumber = -1; //will be at 0 on first call to get512Elevation
arrayOfRequest = [];
//1
var ptrStart= 0;
var pathSliced = path.slice(ptrStart, ptrStart+512);
arrayOfRequest.push(pathSliced);
//2
ptrStart += 512;
pathSliced = path.slice(ptrStart, ptrStart+512);
arrayOfRequest.push(pathSliced);
timerElevation = setInterval(request512Elevation, 1000); //1sec
}
//---------------------------------------------------------
function request512Elevation() {
alert("request512Elevation");
// Still has request to be done
if (currentRequestNumber+1 < numberRequestToDo) {
if (!lastRequestElevationFailed) {
currentRequestNumber++;
}
get512Elevation(arrayOfRequest[currentRequestNumber], currentRequestNumber);
}
// All request completed!
else {
clearInterval(timerElevation);
}
}
//------------------------------------------------------------------------------------------------
function get512Elevation(pathSliced, requestNumber) {
alert("get512PointsElevation" + requestNumber);
var locationElevationRequest = {
'locations': pathSliced
}
elevator.getElevationForLocations(locationElevationRequest, function (results, status) {
alert("ResponseReceived for request:" + requestNumber + ", status" + status + " result length:" + results.length);
if (status != google.maps.ElevationStatus.OK) {
lastRequestElevationFailed = true;
return;
}
lastRequestElevationFailed = false;
var elevations = results;
// Extract the elevation samples from the returned results
for (var i = 0; i < results.length; i++) {
elevationPath.push(elevations[i].location);
}
for (var i = 0; i < results.length; i++) {
dataElevation.addRow(['', elevations[i].elevation]);
}
//last reply received? if yes, we can display the elevation graph
if (currentRequestNumber+1 == numberRequestToDo) {
chart.draw(dataElevation, chartOptions);
}
//TODO: how to make sure response are received in correct order (1,2,3)? setInterval reliable enough?
});
}