how can i get asynchronous reducers data ,i search but didn't get solution
Booking component
cutPick = () => {
this.props.pickup(false);
}
action creator
export function pickup(latlng) {
return function (dispatch) {
dispatch({type:PICKUP_STATE,payload:latlng});
}
}
reducer
import {PICKUP_STATE} from '../actions/types';
export default function (state={},action) {
switch(action.type) {
case PICKUP_STATE:
return {...state,pickup:action.payload}
}
return state;
}
Map component
import React from 'react';
import scriptLoader from "react-async-script-loader";
import config from '../../../config'
import 'antd/dist/antd.css';
import { Icon,Button,Alert,Row, Col} from 'antd';
import {connect} from "react-redux";
import * as actions from "../actions";
class Map extends React.Component{
constructor(props){
super(props);
this.state = {
pick:false,
drop:false,
mapCenter : { lat: 17.3850, lng: 78.4867 },
pickupConfirmButton:false,
dropoffConfirmButton:false
};
this.map=false;
this.directionsService =false;
this.directionsDisplay = false;
this.mapLoaded = false;
this.pickMarker=false;
this.dropMarker=false;
}
//listen map current location event and set marker and pick state
addYourLocationButton = (map) => {
this.pickMarker = new google.maps.Marker ({
map: this.map,
animation: google.maps.Animation.DROP,
position: this.state.pick ? this.state.pick : this.state.mapCenter,
draggable: true
});
if(!this.mapLoaded) {
return false;
}
var controlDiv = document.createElement('div');
let firstChild = document.createElement('button');
firstChild.style.backgroundColor = '#fff';
firstChild.style.border = 'none';
firstChild.style.outline = 'none';
firstChild.style.width = '28px';
firstChild.style.height = '28px';
firstChild.style.borderRadius = '2px';
firstChild.style.boxShadow = '0 1px 4px rgba(0,0,0,0.3)';
firstChild.style.cursor = 'pointer';
firstChild.style.marginRight = '10px';
firstChild.style.padding = '0px';
firstChild.title = 'Your Location';
controlDiv.appendChild(firstChild);
let secondChild = document.createElement('div');
secondChild.style.margin = '5px';
secondChild.style.width = '18px';
secondChild.style.height = '18px';
secondChild.style.backgroundImage = 'url(https://maps.gstatic.com/tactile/mylocation/mylocation-sprite-1x.png)';
secondChild.style.backgroundSize = '180px 18px';
secondChild.style.backgroundPosition = '0px 0px';
secondChild.style.backgroundRepeat = 'no-repeat';
secondChild.id = 'you_location_img';
firstChild.appendChild(secondChild);
// google.maps.event.addListener(map, 'dragend', () => {
// document.getElementById("you_location_img").style.backgroundPosition='0px 0px';
// });
google.maps.event.addListener(this.pickMarker, 'dragend', () =>{
let lat=this.pickMarker.getPosition().lat();
let lng=this.pickMarker.getPosition().lng();
this.setState({pick:{lat:lat,lng:lng}},function () {
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, function(results, status) {
if (status === 'OK') {
document.getElementById('pick').value = results[0].formatted_address;
}
})
// console.log(this.state.pick);
})
if (this.state.pick && this.state.drop){
this.calculateRoute();
}
});
firstChild.addEventListener('click', () => {
let imgX = '0';
let animationInterval = setInterval( () =>{
if (imgX == '-18') imgX = '0';
else imgX = '-18';
document.getElementById("you_location_img").style.backgroundPosition=imgX + 'px 0px';
}, 500);
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition( (position) => {
let latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': latlng}, function(results, status) {
if (status === 'OK') {
document.getElementById('pick').value = results[0].formatted_address;
}
})
if(latlng){
this.setState(()=>({
pick:latlng
}))
}
this.pickMarker.setPosition(latlng);
map.setCenter(latlng);
if (this.state.pick && this.state.drop){
this.calculateRoute();
}
clearInterval(animationInterval);
document.getElementById("you_location_img").style.backgroundPosition='-144px 0px';
});
}
else {
clearInterval(animationInterval);
document.getElementById("you_location_img").style.backgroundPosition='0px 0px';
}
});
controlDiv.index = 1;
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(controlDiv);
}
//load gmaps ,load maps and directions and set center as user current location
componentWillReceiveProps({isScriptLoadSucceed}){
if (isScriptLoadSucceed) {
this.mapLoaded= true;
this.directionsService = new google.maps.DirectionsService();
this.directionsDisplay = new google.maps.DirectionsRenderer({ suppressMarkers: true });
this.map = new google.maps.Map(document.getElementById('map'), {
zoom: 11,
center: this.state.mapCenter
});
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition( (position)=> {
let initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
// console.log(this.state.mapCenter)
this.setState({mapCenter:initialLocation} , ()=> {
// console.log(this.state.mapCenter)
})
this.map.setCenter(initialLocation);
});
}else{
console.log('error in current location')
}
this.directionsDisplay.setMap(this.map);
//icon of current location in map and current loc pickup marker
this.addYourLocationButton(this.map);
//listener for pickup marker when it clicked
this.pickMarker.addListener('click', () =>{
this.pickupMarkerClickListener();
});
}
else{
alert("Something went wrong, plz check internet Connection")
}
}
//for Refs
componentDidMount() {
this.props.onRef(this);
}
//for Refs
componentWillUnmount() {
this.props.onRef(null);
}
// this function pick state false when user click on cut pick address from pickup field and set direction false also
isPickEmpty=(emptyPickState)=>{
console.log(this.props.pickupProps);
this.setState({pick:emptyPickState},function () {
this.pickMarker.setMap(null);
this.directionsDisplay.set('directions', null);
//sending false as distance to BookingDetails
this.props.routeCalc(false);
});
};
//it handle search hint of google place api (getting data from Booking Form)
pickupSearch =(pickupAddress) =>{
let options = {
types: [],
componentRestrictions: {
'country': 'IN'
}
};
let inputPick = document.getElementById('pick');
const autocompletePick = new google.maps.places.Autocomplete(inputPick, options);
autocompletePick.bindTo('bounds', this.map);
google.maps.event.addListener(autocompletePick, 'place_changed', () => {
let place =autocompletePick.getPlace();
let lat = place.geometry.location.lat(),
lng = place.geometry.location.lng();
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, function(results, status) {
if (status === 'OK') {
document.getElementById('pick').value = results[0].formatted_address;
}
});
this.pickUp({lat:lat,lng:lng})
});
}
//this function put pick marker on pickup search
pickUp = (pick) => {
// console.log(pick)
if(this.pickMarker){
this.pickMarker.setMap(null);
}
this.setState({pick:pick}, () => {
// console.log(this.state.pick);
var infoWindow = new google.maps.InfoWindow;
this.pickMarker = new google.maps.Marker({
map:this.map,
animation: google.maps.Animation.DROP,
position: this.state.pick,
draggable: true
});
infoWindow.setPosition(this.state.pick);
// infoWindow.setContent('Location found.');
// infoWindow.open(this.map);
this.map.setCenter(this.state.pick);
this.pickMarker.addListener('click', () =>{
this.pickupMarkerClickListener();
});
google.maps.event.addListener(this.pickMarker, 'dragend', () =>{
this.pickupMarkerDragListener();
});
this.focus.scrollIntoView();
})
if (this.state.pick && this.state.drop){
this.calculateRoute();
}
};
//this function invoke click and drag function of pickup marker
pickupMaker=()=>{
this.setState({pickupConfirmButton:false});
this.map.setZoom(11);
if(this.pickMarker){
this.pickMarker.setMap(null);
}
google.maps.event.clearListeners(this.map, 'center_changed');
this.pickMarker = new google.maps.Marker ({
map: this.map,
animation: google.maps.Animation.DROP,
position: this.state.pick,
draggable:true
});
if(this.dropMarker){
this.dropMarker.setVisible(true);
}
//listening on drag of pick marker
google.maps.event.addListener(this.pickMarker, 'dragend', () => {
this.pickupMarkerDragListener();
console.log('marker')
});
//listening on click of pick marker
this.pickMarker.addListener('click', () =>{
this.pickupMarkerClickListener();
});
//if both state are set the calculate the root
if (this.state.pick && this.state.drop){
this.calculateRoute();
}
};
//this function handle click event of pick Marker
pickupMarkerClickListener = () => {
if(this.dropMarker){
this.dropMarker.setVisible(false);
}
this.directionsDisplay.set('directions', null);
this.setState({pickupConfirmButton:true});
this.map.setCenter(this.pickMarker.getPosition());
this.map.setZoom(16);
this.map.addListener('center_changed', () => {
let lat=this.map.getCenter().lat();
let lng=this.map.getCenter().lng();
this.setState({pick:{lat:lat,lng:lng}},function () {
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, function(results, status) {
if (status === 'OK') {
document.getElementById('pick').value = results[0].formatted_address;
}
})
// console.log(this.state.pick);
});
this.pickMarker.setPosition({lat:lat,lng:lng});
// console.log(this.map.getCenter().lat(),this.map.getCenter().lng(),this.pickMarker.getPosition())
});
};
//This function Handle drage event of pick marker
pickupMarkerDragListener = () => {
console.log('dragged');
let lat=this.pickMarker.getPosition().lat();
let lng=this.pickMarker.getPosition().lng();
this.setState({pick:{lat:lat,lng:lng}}, () => {
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, (results, status) => {
if (status === 'OK') {
document.getElementById('pick').value = results[0].formatted_address;
}
})
console.log(this.state.pick);
})
if ((this.state.pick && this.state.drop) && (this.state.pickupConfirmButton === false && this.state.dropoffConfirmButton ===false)){
this.calculateRoute();
}
}
// this function drop state false when user click on cut drop address from dropoff field and set direction false also
isDropEmpty=(emptyDropState)=>{
// console.log(emptyPickState);
// console.log(this.state.pick);
this.setState({drop:emptyDropState},function () {
// this.pickMarker=false;
this.dropMarker.setMap(null);
this.directionsDisplay.set('directions', null);
//sending false as distance to BookingDetails
this.props.routeCalc(false);
});
};
//it handle drop search hint of google place api (getting data from Booking Form)
dropoffSearch = (dropoffSearch) =>{
let options = {
types: [],
componentRestrictions: {
'country': 'IN'
}
};
const autocompleteDrop = new google.maps.places.Autocomplete(document.getElementById('drop'), options);
autocompleteDrop.bindTo('bounds', this.map);
google.maps.event.addListener(autocompleteDrop, 'place_changed', () => {
let place =autocompleteDrop.getPlace();
let lat = place.geometry.location.lat(),
lng = place.geometry.location.lng();
// this.props.dropHandler({lat:lat,lng:lng})
//
// this.setState({drop:place.name});
// let lat = place.geometry.location.lat(),
// lng = place.geometry.location.lng();
//putting place in pick field
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, function(results, status) {
if (status === 'OK') {
// console.log(results[0].formatted_address)
document.getElementById('drop').value = results[0].formatted_address;
}
});
this.dropOff({lat:lat,lng:lng})
});
};
//this function put drop marker on dropoff search(function invoked from Booking Details)
dropOff = (drop) => {
if (this.dropMarker){
this.dropMarker.setMap(null);
}
this.setState({drop:drop}, () => {
// console.log(this.state.drop);
var infoWindow = new google.maps.InfoWindow;
this.dropMarker = new google.maps.Marker({
map:this.map,
animation: google.maps.Animation.DROP,
position: this.state.drop,
draggable: true
});
infoWindow.setPosition(this.state.drop);
// infoWindow.setContent('Location found.');
// infoWindow.open(this.map);
this.map.setCenter(this.state.drop);
// console.log(this.state.drop);
google.maps.event.addListener(this.dropMarker, 'dragend', () =>{
this.dropoffMarkerDragListener();
});
this.dropMarker.addListener('click', () =>{
this.dropoffMarkerClickListener();
});
if (this.state.pick && this.state.drop){
this.calculateRoute();
}
this.focus.scrollIntoView();
})
// if (this.state.pick && this.state.drop){
// this.calculateRoute();
// }
};
//this function invoke click and drag function of drop marker
dropoffMaker= () =>{
this.setState({dropoffConfirmButton:false});
this.map.setZoom(11);
this.dropMarker.setMap(null);
google.maps.event.clearListeners(this.map, 'center_changed');
this.dropMarker = new google.maps.Marker ({
map: this.map,
animation: google.maps.Animation.DROP,
position: this.state.drop,
draggable: true
});
if(this.pickMarker){
this.pickMarker.setVisible(true);
}
google.maps.event.addListener(this.dropMarker, 'dragend', () =>{
this.dropoffMarkerDragListener();
});
this.dropMarker.addListener('click', () =>{
this.dropoffMarkerClickListener();
});
if (this.state.pick && this.state.drop){
this.calculateRoute();
}
}
//this function handle click event of Drop Marker
dropoffMarkerClickListener=()=>{
this.pickMarker.setVisible(false);
this.directionsDisplay.set('directions', null);
this.setState({dropoffConfirmButton:true});
this.map.setCenter(this.dropMarker.getPosition());
this.map.setZoom(16);
this.map.addListener('center_changed', () => {
let lat=this.map.getCenter().lat();
let lng=this.map.getCenter().lng();
this.setState({drop:{lat:lat,lng:lng}},function () {
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, function(results, status) {
if (status === 'OK') {
document.getElementById('drop').value = results[0].formatted_address;
}
});
});
this.dropMarker.setPosition({lat:lat,lng:lng});
console.log(this.map.getCenter().lat(),this.map.getCenter().lng(),this.dropMarker.getPosition())
});
}
//This function Handle drage event of drop marker
dropoffMarkerDragListener= () => {
let lat=this.dropMarker.getPosition().lat();
let lng=this.dropMarker.getPosition().lng();
this.setState({drop:{lat:lat,lng:lng}},function () {
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, function(results, status) {
if (status === 'OK') {
document.getElementById('drop').value = results[0].formatted_address;
}
})
console.log(this.state.drop);
})
if ((this.state.pick && this.state.drop) && (this.state.pickupConfirmButton === false && this.state.dropoffConfirmButton ===false)){
this.calculateRoute();
}
};
//this function set direction and calculate the root of pick and drop
calculateRoute = () =>{
var request ={
origin:this.state.pick,
destination:this.state.drop,
travelMode:"DRIVING"
};
this.directionsService.route(request,(result,status) => {
if(status== "OK"){
console.log(result.routes[0].legs[0].distance);
this.props.routeCalc(result.routes[0].legs[0].distance);
this.directionsDisplay.setDirections(result);
}
});
};
render(){
return(
<div className="Map" ref={node => this.focus = node}>
<Alert
message="Tap or Drag Marker[s] to set exact location Then Click on Confirm Location"
type="info"
showIcon
/>
<div id="map" style={{height: "500px"}}></div>
{this.state.pickupConfirmButton && <Button className="cnfrmBtn" size="large" onClick={this.pickupMaker}>Confirm Location</Button> }
{this.state.dropoffConfirmButton && <Button className="cnfrmBtn" size="large" onClick={this.dropoffMaker}>Confirm Location</Button> }
</div>
)
}
}
function mapStateToProps (state) {
return {pickupProps:state.BookingData.pickup}
}
// export default Map;
const ScriptLoadedMap = scriptLoader(
[config.MapApi]
)(Map);
export default connect(mapStateToProps,actions)(ScriptLoadedMap);
i'm sending false value from Booking to action creator then i'm dispatching and storing value in action in reducer
but when i'm calling pickupProps from Map component first time i'm getting undefined after first time getting false value.
so here my problem is how can i get first time (asynchronous) false value when it called from Booking component.
Related
I have a FullCalendar that takes in an array(selectedEvents) from a function that uses the Location ID that is pulled from the url. The array is built onInit as is the calendar but the calendar has a timeout on it in order to allow the events to populate. When the calendar is initially navigated to from another part of the website, the events for the Default Location are not displayed but they are populated into the selectedEvents array. When I click on another location's calendar, the events are populated and then displayed correctly. The calendar works correctly thereforth. I believe the calendar is taking precedence over the population of events during the first initialization of the calendar even though it is wrapped in a timeout. I've seen this question once before on SO but it was not answered.
I've already tried extending the timeout of the calendar
getLocationEvents(location: PFLocation) {
// if (this.allEvents) {
this.selectedEvents = [];
if (location.events) {
console.log(location.events);
this.eventIdArray = location.events;
for (let event of this.eventIdArray) {
this.eventService.get(event).subscribe(data => {
console.log(data);
this.selectedEvents.push(data);
});
}
} else {
return;
}
console.log(this.selectedEvents);
return this.selectedEvents;
}
getBatchEvents(location: PFLocation) {
var that = this;
if (this.allEvents) {
if (location.batches) {
let batches = location.batches;
for (let batch of batches) {
this.batchService.get(batch).subscribe(data => {
for (let event of data.events) {
this.eventService
.get(event)
.subscribe(eventData => {
console.log(eventData);
this.selectedEvents.push(eventData);
});
}
});
}
console.log(this.selectedEvents);
console.log('out of Batch Events');
return this.selectedEvents;
}
}
if (!this.allEvents) {
this.selectedEvents = [];
if (location.batches) {
let batches = location.batches;
for (let batch of batches) {
this.batchService.get(batch).subscribe(data => {
for (let event of data.events) {
this.eventService
.get(event)
.subscribe(eventData => {
console.log(eventData);
this.selectedEvents.push(eventData);
});
}
});
}
console.log(this.batchEvents);
console.log('out of Batch Events');
return this.selectedEvents;
}
}
}
getAllEvents(location: PFLocation) {
this.allEvents = true;
var that = this;
that.getLocationEvents(location);
that.getBatchEvents(location);
}
ngOnInit() {
let that = this;
this.sub = this.route.params.subscribe(params => {
this.locationId = params['locationid'];
this.userService
.getLocation(this.locationId)
.subscribe(location => {
console.log('Out of on Init');
this.selectedLocation = JSON.parse(
JSON.stringify(location)
);
that.getAllEvents(this.selectedLocation);
console.log(this.selectedLocation);
});`enter code here`
console.log(this.selectedLocation);
if (this.locationId) {
const today = new Date();
const y = today.getFullYear();
const m = today.getMonth();
const d = today.getDate();
$('#fullCalendar').fullCalendar('removeEvents');
$('#fullCalendar').fullCalendar(
'addEventSource',
that.selectedEvents
);
setTimeout(function() {
$('#fullCalendar').fullCalendar({
viewRender: function(view: any, element: any){
// We make sure that we activate the
perfect scrollbar when the view isn't on Month
if (view.name != 'month') {
var elem = $(element).find('.fc-
scroller')[0];
let ps = new PerfectScrollbar(elem);
}
},
header: {
left: 'title',
center: 'month, agendaWeek, agendaDay',
right: 'prev, next, today'
},
defaultDate: today,
selectable: true,
selectHelper: true,
views: {
month: {
// name of view
titleFormat: 'MMMM YYYY'
// other view-specific options here
},
week: {
titleFormat: ' MMMM D YYYY'
},
day: {
titleFormat: 'D MMM, YYYY'
}
},
eventLimit: true, // allow "more" link when
too many events
select: function(start: any, end: any) {
that.openEventForm();
},
eventClick: function(event, jsEvent) {
that.completeEventForm(event);
}
});
}, 500);
}
});
}
I expect the calendar to be populated the first time I navigate to the page.
Aside from refactoring the backend and eliminating the spaghetti code it wasn't a difficult issue once someone pointed out how the calendar inits. First the calendar has to grab onto the DOM element then it grabs the event source. If it doesn't grab the #calendar then it won't grab the event source until the next time it's initialized and at that point it is using the old event source data(if set up as my code was). "viewRender" needs to happen first, then "removeEvents" then "addEventSource".
getLocationEvents(location: PFLocation) {
if (location.events) {
return this.eventService
.getFaciltyTasks(location._id)
.subscribe(data => {
console.log(data);
this.facilityEvents = data;
});
}
}
getAllBatchEvents(location: PFLocation) {
return this.eventService
.getAllCultivationTasks(location._id)
.subscribe(data => {
console.log(data);
this.cultivationEvents = data;
});
}
getBatchEvents(batchId: string) {
return this.eventService.getBatchTasks(batchId).subscribe(data => {
console.log(data);
this.batchEvents = data;
});
}
editEventForm() {
this.state = 'editEvent';
}
getAllEvents(location: PFLocation) {
var that = this;
return new Promise(resolve => {
return this.eventService
.getAllLocationTasks(location._id)
.subscribe(data => {
console.log(data);
that.selectedEvents = data;
that.calInit();
resolve(that.selectedEvents);
});
});
}
calInit() {
var that = this;
const $calendar = $('#fullCalendar');
console.log(that.locationId);
if (this.selectedEvents) {
const today = new Date();
const y = today.getFullYear();
const m = today.getMonth();
const d = today.getDate();
$calendar.fullCalendar({
viewRender: function(view: any, element: any) {
// We make sure that we activate the perfect scrollbar when the view isn't on Month
if (view.name != 'month') {
var elem = $(element).find('.fc-scroller')[0];
let ps = new PerfectScrollbar(elem);
}
},
customButtons: {
filter: {
text: 'filter',
click: function() {
that.open();
}
}
},
// events: that.selectedEvents,
header: {
left: 'title',
center: 'filter, month, agendaWeek, agendaDay',
right: 'prev, next, today'
},
defaultDate: today,
selectable: true,
selectHelper: true,
views: {
month: {
// name of view
titleFormat: 'MMMM YYYY'
// other view-specific options here
},
week: {
titleFormat: ' MMMM D YYYY'
},
day: {
titleFormat: 'D MMM, YYYY'
}
},
eventLimit: true, // allow "more" link when too many events
select: function(start: any, end: any) {
that.openEventForm();
},
eventClick: function(event, jsEvent) {
that.eventLocation = new PFLocation({});
that.eventBatch = new Batch();
that.eventRoom = new Room();
that.viewEvent(event);
}
});
$calendar.fullCalendar('removeEvents');
$calendar.fullCalendar('addEventSource', that.selectedEvents);
}
}
ngOnInit() {
// const $calendar = $('#fullCalendar');
let that = this;
// that.filter = false;
this.sub = this.route.params.subscribe(params => {
that.locationId = params['locationid'];
if (that.locationId) {
that.AuthService.getCurrentUser().then(user => {
that.currentUser = user;
var locations = that.currentUser.locations.admin.concat(
that.currentUser.locations.user
);
var location = find(locations, function(location) {
return location._id == that.locationId;
});
console.log(location);
console.log(that.currentUser);
});
}
this.userService
.getLocation(this.locationId)
.subscribe(location => {
console.log('Out of on Init');
this.selectedLocation = JSON.parse(
JSON.stringify(location)
);
that.getAllEvents(this.selectedLocation);
console.log(this.selectedLocation);
});
console.log(this.selectedLocation);
});
}
My app creates a new item, and I want to retrieve the key to use in a server script. The data variable returns null though. This is what I have:
function addItem(addButton) {
var addItemPage = addButton.root;
if (!addItemPage.validate()) {
return;
}
var props = addItemPage.properties;
var itemDs = addItemPage.datasource;
props.Creating = true;
itemDs.saveChanges({
success: function(key) {
props.Creating = false;
if (app.currentPage !== app.pages.EditItem) {
return;
}
var newProjectItem = itemDs.item;
newProjectItem._loadHistory();
gotoEditItemPage(newProjectItem._key, true);
return newProjectItem;
},
failure: function(error) {
props.Creating = false;
console.error(error);
}
});
gotoEditItemPage();
var data = app.datasources.ProjectItems.item._key;
google.script.run.withSuccessHandler(function(value){
alert("Created");
}).createDoco(data);
}
This is not neat by any means, but I fixed it by creating a new function:
function addItem(addButton, key) {
var addItemPage = addButton.root;
if (!addItemPage.validate()) {
return;
}
var props = addItemPage.properties;
var itemDs = addItemPage.datasource;
props.Creating = true;
itemDs.saveChanges({
success: function() {
props.Creating = false;
if (app.currentPage !== app.pages.EditItem) {
return;
}
var newProjectItem = itemDs.item;
newProjectItem._loadHistory();
gotoEditItemPage(newProjectItem._key, true);
var key = newProjectItem._key;
value(key);
},
failure: function(error) {
props.Creating = false;
console.error(error);
}
});
gotoEditItemPage();
function value(record){
var data = record;
google.script.run.withSuccessHandler(function(value){
alert("Created");
}).createDoco(data);
}
}
Can anyone tell me how to show all popup of markers in openlayers 3 map. I searched many sites but couldn't get any answer please anyone know about this then help me
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.TileJSON({
url: 'https://api.tiles.mapbox.com/v3/mapbox.geography-class.json?secure',
crossOrigin: 'anonymous'
})
})
],
overlays: [overlay],
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([0, 50]),
zoom: 2
})
});
var vectorSource = new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([16.37, 48.2])),
name: 'London'
}),
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([-0.13, 51.51])),
name: 'NY'
}),
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([30.69, 55.21])),
name: 'Paris'
})
]
});
var markers = new ol.layer.Vector({
source: vectorSource,
style: new ol.style.Style({
image: new ol.style.Icon({
src: '//openlayers.org/en/v3.12.1/examples/data/icon.png',
anchor: [0.5, 1]
})
})
});
map.addLayer(markers);
function showpopup(){
// For showing popups on Map
var arrayData = [1];
showInfoOnMap(map,arrayData,1);
function showInfoOnMap(map, arrayData, flag) {
var flag = 'show';
var extent = map.getView().calculateExtent(map.getSize());
var id = 0;
var element = document.getElementById('popup');
var popup = new ol.Overlay({
element: element,
positioning: 'center'
});
map.addOverlay(popup);
if (arrayData != null && arrayData.length > 0) {
arrayData.forEach(function(vectorSource) {
/* logMessage('vectorSource >> ' + vectorSource); */
if (vectorSource != null && markers.getSource().getFeatures() != null && markers.getSource().getFeatures().length > 0) {
markers.getSource().forEachFeatureInExtent(extent, function(feature) {
/* logMessage('vectorSource feature >> ' + feature); */
console.log("vectorSource feature >> " + markers.getSource().getFeatures());
if (flag == 'show') {
var geometry = feature.getGeometry();
var coord = geometry.getCoordinates();
popup.setPosition(coord);
/* var prop;
var vyprop = ""; */
$(element).popover({
'position': 'center',
'placement': 'top',
'template':'<div class="popover"><div class="popover-content"></div></div>',
'html': true,
'content': function() {
var string = [];
var st = feature.U.name;
if (st != null && st.length > 0) {
var arrayLength = 1;
string = "<table>";
string += '<tr><td>' + st + "</table>";
}
return string;
}
});
$(element).popover('show');
} else {
$(element).popover('destroy');
}
});
}
});
}
};
}
I used this code in my file but it show only one popup on all markers please someone tell me how to show all markers popup simultaneously.
I'm not sure exactly what you're trying to show in your popups, but I would probably try this approach. This extends the ol.Overlay class, allowing you to get the map object and attach a listener which you can use to grab the feature that was clicked. Is this what you're trying to accomplish?
function PopupOverlay() {
var element = document.createElement('div');
$(element).popover({
template: '<div class="popover"><div class="popover-content"></div></div>',
placement: 'top',
position: 'center',
html: true
});
ol.Overlay.call(this, {
element: element
});
}
ol.inherits(PopupOverlay, ol.Overlay);
PopupOverlay.prototype.setMap = function (map) {
var self = this;
map.on('singleclick', function (e) {
map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
ol.Overlay.prototype.setPosition.call(self, feature.getGeometry().getCoordinates());
var el = self.getElement();
$(el).data('bs.popover').options.content = function () {
// EDIT THE POPOVER CONTENT
return feature.get('name');
};
$(el).popover('show');
});
});
ol.Overlay.prototype.setMap.call(this, map);
};
Check out this example
So after your comment, I see what you're trying to do now. I would say that you want to take the same basic approach, make a class that overrides ol.Overlay, but this time just loop through all the features, creating an overlay for each feature.
This Updated Example
function PopoverOverlay(feature, map) {
this.feature = feature;
var element = document.createElement('div');
$(element).popover({
template: '<div class="popover"><div class="popover-content"></div></div>',
placement: 'top',
position: 'center',
html: true
});
ol.Overlay.call(this, {
element: element,
map: map
});
};
ol.inherits(PopoverOverlay, ol.Overlay);
PopoverOverlay.prototype.togglePopover = function () {
ol.Overlay.prototype.setPosition.call(this, this.feature.getGeometry().getCoordinates());
var self = this;
var el = this.getElement();
$(el).data('bs.popover').options.content = function () {
// EDIT THE POPOVER CONTENT
return self.feature.get('name');
};
$(el).popover('toggle');
};
// create overlays for each feature
var overlays = (function createOverlays () {
var popupOverlays = [];
vectorSource.getFeatures().forEach(function (feature) {
var overlay = new PopoverOverlay(feature, map);
popupOverlays.push(overlay);
map.addOverlay(overlay);
});
return popupOverlays;
})();
// on click, toggle the popovers
map.on('singleclick', function () {
for(var i in overlays) {
overlays[i].togglePopover();
}
});
Now when you click anywhere on the map, it should call the togglePopover method and toggle the popover on the individual element.
I'm using Google Places Autocomplete and Google Maps api.
In my js I wrapped the listener for the autocomplete in order to simulate a combination of "down arrow" and "enter" events if there is no autocomplete result selected.
See the following snippet:
var pac_input = document.getElementById('locatorPlaceSearch');
var orig_listener;
(function pacSelectFirst(input) {
// store the original event binding function
var _addEventListener = (input.addEventListener) ? input.addEventListener : input.attachEvent;
function addEventListenerWrapper(type, listener) {
// Simulate a 'down arrow' keypress on hitting 'return' when no pac suggestion is selected,
// and then trigger the original listener.
if (type == "keydown") {
orig_listener = listener;
listener = function (event) {
var suggestion_selected = $(".pac-item-selected").length > 0;
if (event.which == 13 && !suggestion_selected) {
var simulated_downarrow = $.Event("keydown", {
keyCode: 40,
which: 40
});
orig_listener.apply(input, [simulated_downarrow]);
}
orig_listener.apply(input, [event]);
};
}
_addEventListener.apply(input, [type, listener]);
mapsListener = listener;
}
input.addEventListener = addEventListenerWrapper;
input.attachEvent = addEventListenerWrapper;
})(pac_input);
autocomplete = new google.maps.places.Autocomplete(pac_input,
{
componentRestrictions: { country: $('#hdnLocatorPlace').val() },
types: ['geocode']
});
Now I have a "Search" button, and I want to trigger a "down arrow" and "enter" as well. I tried this code but it's not firing the keydown event on the listener:
$('#searchAP').off('click').on('click', function (e) {
e.preventDefault();
e.stopPropagation();
setTimeout(function() {
$('#locatorPlaceSearch').focus();
$('#locatorPlaceSearch').click();
setTimeout(function() {
var sev = $.Event("keydown", {
keyCode: 13,
which: 13
});
//mapsListener.apply($('#locatorPlaceSearch'), [sev]);
$('#locatorPlaceSearch').trigger(sev);
},1000);
}, 1000);
//$('#locatorPlaceSearch').trigger(sev);
});
What's wrong with this code?
I can't tell you exactly what's going on there, as it seems the event will not be triggered at all(at least your listener will not be called).
You may trigger the event by using the native DOM-method (dispatchEvent):
google.maps.event.addDomListener(window, 'load', function() {
var pac_input = document.getElementById('locatorPlaceSearch');
var orig_listener;
(function pacSelectFirst(input) {
// store the original event binding function
var _addEventListener = (input.addEventListener) ? input.addEventListener : input.attachEvent;
function addEventListenerWrapper(type, listener) {
// Simulate a 'down arrow' keypress on hitting 'return' when no pac suggestion is selected,
// and then trigger the original listener.
if (type == "keydown") {
orig_listener = listener;
listener = function(event) {
var suggestion_selected = $(".pac-item-selected").length > 0;
if (event.which == 13 && !suggestion_selected) {
var simulated_downarrow = $.Event("keydown", {
keyCode: 40,
which: 40
});
orig_listener.apply(input, [simulated_downarrow]);
}
orig_listener.apply(input, [event]);
};
}
_addEventListener.apply(input, [type, listener]);
mapsListener = listener;
}
input.addEventListener = addEventListenerWrapper;
input.attachEvent = addEventListenerWrapper;
})(pac_input);
autocomplete = new google.maps.places.Autocomplete(pac_input, {
componentRestrictions: {
country: $('#hdnLocatorPlace').val()
},
types: ['geocode']
});
$('#searchAP').off('click').on('click', function(e) {
var keydown = document.createEvent('HTMLEvents');
keydown.initEvent("keydown", true, false);
Object.defineProperty(keydown, 'keyCode', {
get: function() {
return 13;
}
});
Object.defineProperty(keydown, 'which', {
get: function() {
return 13;
}
});
pac_input.dispatchEvent(keydown);
});
});
<script src="https://code.jquery.com/jquery-latest.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=places"></script>
<input id="locatorPlaceSearch">
<input type="submit" id="searchAP">
<input type="hidden" id="hdnLocatorPlace" value="de">
Another solution, using the event-wrapper of the maps-API:
google.maps.event.addDomListener(window, 'load', function() {
(function(input, opts, nodes) {
var ac = new google.maps.places.Autocomplete(input, opts);
google.maps.event.addDomListener(input, 'keydown', function(e) {
if (e.keyCode === 13 && !e.triggered) {
google.maps.event.trigger(this, 'keydown', {
keyCode: 40
})
google.maps.event.trigger(this, 'keydown', {
keyCode: 13,
triggered: true
})
}
});
for (var n = 0; n < nodes.length; ++n) {
google.maps.event.addDomListener(nodes[n].n, nodes[n].e, function(e) {
google.maps.event.trigger(input, 'keydown', {
keyCode: 13
})
});
}
}
(
document.getElementById('locatorPlaceSearch'), {
componentRestrictions: {
country: document.getElementById('hdnLocatorPlace').value
},
types: ['geocode']
}, [{
n: document.getElementById('searchAP'),
e: 'click'
}]
));
});
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=places"></script>
<input id="locatorPlaceSearch">
<input type="submit" id="searchAP">
<input type="hidden" id="hdnLocatorPlace" value="de">
Long time reader/ first time poster here, with a question I suspect will be easy to answer but help me out no end.
I simply want to i) retrieve the user's location, ii) display an icon at this location, and iii) Have a button labelled 'Find Me' that pans the map to this location.
I have i) and ii) working, but although I have other buttons that pan to a particular location, this one doesn't seem to work:
var viewportHeight = $(window).height();
var mapHeight = viewportHeight - 93;
var map;
var union = new google.maps.LatLng(53.806828, -1.555999);
var userLocation;
var userIcon = 'userIcon.png';
var parkinson = new google.maps.LatLng(53.808, -1.553);
var unionDescription = '<div id="content">' + '<div id="siteNotice">' + '</div>' + '<h2 id="firstHeading" class="firstHeading">Your Union</h2>' + '<div id="bodyContent">' + '<p>Heres a bit about us</p>' + '</div>' + '</div>';
//Try and get the user's location
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
var userLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
$('#map_canvas').gmap('addMarker', {
'position': userLocation,
'bounds': false,
'icon': userIcon
});
});
};
//initialise the map
$(function () {
$('#map_canvas').gmap({
'center': union,
'zoom': 16,
'mapTypeId': google.maps.MapTypeId.ROADMAP,
'styles': campusStyles,
'minZoom': 15,
'maxZoom': 17
}).bind('init', function (ev, map) {
$('#map_canvas').gmap('addMarker', {
'position': parkinson,
'bounds': false
}).click(function () {
$('#map_canvas').gmap('openInfoWindow', {
'content': 'Hello World!'
}, this);
});
$('#map_canvas').gmap('addMarker', {
'position': union,
'bounds': true
}).click(function () {
$('#map_canvas').gmap('openInfoWindow', {
'content': unionDescription
}, this);
});
$('#map_canvas').height(mapHeight);
google.maps.event.trigger(map, 'resize');
$('#unionButton').click(function () {
map.panTo(union);
});
$('#findMe').click(function () {
map.panTo(userLocation);
});
$('#map_canvas').height(mapHeight);
});
});
Thing I'm actually working on here: http://jdp.org.uk/tests/mapstest4.html
I don't know why but my navigator geolocation is not working, so I just bypassed that requirement and hard-coded a user LatLng. What worked for me was cutting and pasting the whole block if(navigator.geolocaton) to directly below the block with the line $('#unionButton').click(function(){map.panTo(union);});. It appears that map was not yet defined where you had the geolocation code.
From my testing, smooth panning only happens when the current position is close to the target. http://jsfiddle.net/EejRt/
I have:
$('#map_canvas').height(mapHeight);
google.maps.event.trigger(map, 'resize');
$('#unionButton').click(function(){map.panTo(union);});
$('#map_canvas').height(mapHeight);
//if (navigator.geolocation) {
// navigator.geolocation.getCurrentPosition(function(position) {
// var userLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
var userLocation = new google.maps.LatLng(53.8018,-1.553);
$('#map_canvas').gmap('addMarker', {'position': userLocation, 'bounds': false, 'icon' : userIcon });
$('#findMe').click(function(){map.panTo(userLocation)});
// });
// };