Backbone.js fetch issues with Google Maps - backbone.js

With backbone I am fetching results from Google maps to return markers of places where the user is. The results populate a collection which I clear everytime the user moves the map as a new fetch occurs based on the new location bounds (I am using the google map idle event to get this information and changing the URL of the collection).
To manage the markers I populate an array with each marker.
The issue I am having is I get the first set of markers but it does not write in any new markers when the map is moved and when you inspect the markers array its the same results as last. If I do an AJAX call I get the desired results, but I want to keep this all within a backbone collection as I do other processes with the model.
/* Tracking Page Items */
var allPlace = Backbone.Model.extend({
createMarker:function(){
var marker = new google.maps.Marker({
position: this.getLatLng(),
title: this.get("name"),
location_type: this.get("type")
});
return marker;
}
});
var MarkersCollection = Backbone.Collection.extend({
model: allPlace,
url:function(){
return '/'
}
})
var markersArray = [];
var mapAll = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'render', 'createMarkers'); // get access to this in other methods
this.collection.bind('reset', this.render, this);
},
render: function() {
// Load map scripts and initialise
if(typeof google === "undefined"){
nzp.loadGoogleMap();
} else {
nzp.initializeMap();
};
// Current location
myLocations = {
lat: this.collection.lat,
lng: this.collection.lng
};
// Listen for map movement
var self = this;
google.maps.event.addListener(map, 'idle', function() {
var bounds = map.getBounds();
var lat1 = bounds.ca.b;
var lng1 = bounds.ea.b;
var lat2 = bounds.ca.f;
var lng2 = bounds.ea.f;
self.showMarkers(lat1, lng1, lat2, lng2);
});
},
// update URL based on new bround
showMarkers: function(lat1, lng1, lat2, lng2) {
var markerCollection = new MarkersCollection;
nzp.infoWindow = new google.maps.InfoWindow();
lat = myLatlng.Xa;
lng = myLatlng.Ya;
lat1 = lat1;
lng1 = lng1;
lat2 = lat2;
lng2 = lng2;
// Collection URL build from parameter adn current location
markerCollection.url = "http://blah.com/locator/api/locations?api_key=XXX&nearby_latitude="+lat+"&nearby_longitude="+lng+"&lat1="+lat1+"&lng1="+lng1+"&lat2="+lat2+"&lng2="+lng2+"&max=10&format=jsonp&callback=?";
// Fetch collection
markerCollection.fetch({
success: function(results) {
// Clear the markers array
for (i in markersArray) {
markersArray[i].setMap(null);
}
markersArray.length = 0;
// Loop over items in collection
results.map(function(item){
var marker = item.createMarker();
marker.setMap(map);
// Create a marker based on each item
(function(marker, item) {
google.maps.event.addListener(marker, "click", function(e) {
nzp.infoWindow.setContent(infowindowContent(item)); // Info window content is processed in a method within the model
nzp.infoWindow.open(map, marker);
});
// Place each marker in the markers arrya
markersArray.push(marker); // Push markers into an array so they can be removed
})(marker, item);
}, this);
}
});
// Set markers to vidsible
$.each(markersArray, function(index, item){
markersArray[index].setVisible(true);
});
});

Fixed this. The issue was related to the values being passed to the API and not how I was updating the collection URL as I thought.
I was passing a bounds and a current location and bounds which was causing the API to always return the same results. The working AJAX version I had of the code had a typo in the URL which actually allowed the API to return the correct results.

Related

How to work with maps in different views

I'm trying to show different maps in different views but charging 1 on 1 map view, switch to another map not load, there is no mistake to launch the browser so I could not decide because I can not keep showing other maps. I'm doing as follows:
$scope.cargarUbicacion = function () {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
latitud_actual = position.coords.latitude;
longitud_actual = position.coords.longitude;
console.log(latitud_actual);
console.log(longitud_actual);
var mapOptions = {
center: new google.maps.LatLng(latitud_actual, longitud_actual),
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scrollwheel: false
};
map = new google.maps.Map(document.getElementById("mapa_ubicacion"), mapOptions);
$scope.setMarker(map, new google.maps.LatLng(latitud_actual, longitud_actual), 'Yo', '');
});
}
}
$scope.setMarker = function(map, position, title, content) {
var marker;
var markerOptions = {
position: position,
map: map,
title: title,
icon: 'http://maps.google.com/mapfiles/ms/icons/green-dot.png'
};
marker = new google.maps.Marker(markerOptions);
markers.push(marker); // add marker to array
google.maps.event.addListener(marker, 'click', function () {
// close window if not undefined
if (infoWindow !== void 0) {
infoWindow.close();
}
// create new window
var infoWindowOptions = {
content: content
};
infoWindow = new google.maps.InfoWindow(infoWindowOptions);
infoWindow.open(map, marker);
});
}
I am using this code in multiple controllers, my idea is encapsulated and can occupy the same code 1 time in several views. Whenever I change the id map to avoid that problem, thinking that this was the cause that did not load the map.
Any idea how to do what I need or that is failing to load maps?
Thank you.
I personnaly do the following :
The code taht you want to reuse put it into a global variable such as :
Then into your control, you can extend it with this mapExtend
global.MapExtend = function($scope, $rootScope, leafletData) {
// ... all your functions to reuse
};
// In your main controler, extend it with your map capabilities with angular.extend
angular.extend(myCtrl, new MapExtend($scope, $rootScope, leafletData));

angularjs google maps $location.search does not change after autocomplete place_change

The initial request url is http://localhost/#/map?lat=33.73060000952102&lng=-117.12635126323244
In my project I'm using Google Maps Autocomplete Service which autopopulates the text field with address predictions and upon select an address the map is centered to that location. My place_changed event listener is fired successfully and my controllers setLocation function is called successfully. However, the URL in the address bar is NOT updated with the new lat and lng param values.
If I call $scope.getProjectsByCenter() from an ng-click in the html it works. Somehow event chain in place_changed conflicts with $location.search.
Anyone have any thoughts as to why?
angular: app.js
var app = angular.module('projectmapsApp', []);
app.controller('MainMapController', function($scope,$location){
$scope.setLocation = function(lat,lng){
$location.search('lat',lat);
$location.search('lng',lng);
console.log($location.search()); //This logs an object with the new lat and lng
};
$scope.getProjectsByCenter = function(){
var center = getProjectsByCenter();
$scope.setLocation(center.lat(),center.lng());
};
});
vanilla: map.js
function initializeMap() {
var map = new google.maps.Map(document.getElementById("map-canvas"), {
center: {lat: 33.868670, lng: -117.796783}
});
var input = document.getElementById('place-search');
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.addListener('place_changed', function() {
var place = autocomplete.getPlace();
if (!place.geometry) {
return;
}
var lat = place.geometry.location.lat();
var lng = place.geometry.location.lng();
angular.element('#MainMapController').scope().setLocation(lat,lng);
};
};
Found the answer. $apply()
My setLocation now looks like this:
$scope.setLocation = function(lat,lng){
$location.search('lat',lat);
$location.search('lng',lng);
$scope.$apply();
};
Great article here: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

Local-storage backbone models

I am trying to use, https://github.com/jeromegn/Backbone.localStorage, to store models. I ve got a JSON and I am fetch data with backbone and I am trying to local store the fetched data. The first variable of json file is a time key called tstamp. How can I store and retrieve data based on tstamp attribute?? My code:
// Backbone model Creation for highlight
var HighlightModel = Backbone.Model.extend({
defaults: {
tstamp: "1234",
att: "",
},
initialize: function () {
}
});
//Backbone model initialization
highlight = new HighlightModel();
var HighlightList = Backbone.Collection.extend({
model: HighlightModel,
localStorage: new Backbone.LocalStorage("highlightList"),
url: 'data.json'
});
var HighlightView = Backbone.View.extend({
el: "#highlights",
template: _.template($('#highlightTemplate').html()),
render: function (eventName) {
_.each(this.model.models, function (highlight) {
var highlightTemplate = this.template(highlight.toJSON());
//push data to obj for highlight script
mp = highlight.toJSON();
// Add data to DOM element
$(this.el).html(highlightTemplate);
}, this);
return this; // .remove(); to stop displaying
}
});
var highlights = new HighlightList([highlight]);
var highlightsView = new HighlightView({
model: highlights
});
// Fetching data from server every n seconds
setInterval(function () {
highlights.fetch({
reset: true
});
highlight.add(sentiments);
highlights.save();
}, htCycle); // Time in milliseconds
highlights.bind('reset', function () {
highlightsView.render();
console.log('render');
});
EDIT:
I change my code a little bit, now i have at local storage just store the default model {"tstamp":"1234","att":"","id":"4fb1b437-0e37-8eb7-ed3c-cbd9d0dcff98"}. I want to store the fetched data from server to localstorage.

How to reset my collection on load and later to go just update

In my Backbone function, i am fetching the data from server as first time.(it has bunch of datas) and i am adding to document. According to the client requirement i should keep watch the server every 10sec, and need to apply the elements to the document. I am always using the "reset" call back to render the elements..
But i need to apply all the element to document as firt time, later part just it is enough to update, how can i do like..?
here is a partial stuff from my code:
initialize:function(params){
_.bindAll(this);
var that = this;
this.listItems = ["projectName","assignedTo","projectName"];
this.classItems = ["projectName","assignedTo","sortBy"];
this.listCatch = [];this.boardCatch=[];
this.params = params;
for(var i=0;i<this.listItems.length; i+=1){
this.listCatch[i] = [];
}
this.collection = new singleton.collection;
this.collection.on('reset', this.render);
//on load resetting..
var dataFetcher = function(){
that.collection.fetch();
appDataFetcher = setTimeout(dataFetcher,10000);
// as well all times resetting the whole data...
};
var appDataFetcher = setTimeout(dataFetcher,0);
},
render:function(){
this.listCollection = this.collection;
this.boardCollection = this.collection;
this.listCollect();
this.boardViewSet();
},
listCollect:function(){
var that = this;
_(this.listItems).forEach(function(key,i){
var uniqur = _.uniq(that.listCollection.models, function(item){
return item.get(key);
});
that.listViewSet(key,i,uniqur);
});
},
I set my fetching process like this.. it works fine as like i expected. But if this is not correct approach let any one correct me..?
this.collection.on('add', this.render);
this.collection.on('remove', this.render);
var dataFetcher = function(){
that.collection.fetch({update:true,remove:true});
appDataFetcher = setTimeout(dataFetcher,10000);
};
var appDataFetcher = setTimeout(dataFetcher,0);

Backbone.js - custom collection not working

In the backbone.js, for the purpose of filtering the data, i am fetching by click the element.
and i am saving the collection as newcollection. but i unable to get any data.
what is wrong with my code...
my code :
taskListPhraseI.collection = Backbone.Collection.extend({ // collection fetching
model:taskListPhraseI.model,
url : 'data/data.json',
});
taskListPhraseI.allView = Backbone.View.extend({
el:$('.boardHolder'),
events:{
'click span.green' : 'filterIt'
},
initialize:function(){
var that = this;_.bindAll(this);
this.collection = new taskListPhraseI.collection(); //initial stage i am fetching
this.collection.fetch({success:that.render});
this.on('change:filterType', this.setNewType); //on click trigger my custom method to get the collection again
//this.on('reset:filterType', this.setNewType);
},
setNewType:function(){
var newCollection = new taskListPhraseI.collection(); // my custom collection
newCollection.fetch(); // fetching
this.collection.reset(newCollection,{ silent: true }) // triggering rest
var filterType = this.filterType,
filtered = _.filter(this.collection.models, function (item) {
return item.get("dueDays") === filterType;
});
console.log(newCollection.models); // not working... why?
console.log(this.collection.models);// works
this.collection.reset(filtered);
},
or the way i am doing wrong.. to filter the collection
any one guide me a correct way of process...
thanks in advance
fetch is async. Execute your code after collection will be fetched
newCollection.fetch({context:this}).done(function() {
// your code
})
Plus this is not correct reset method usage:
this.collection.reset(newCollection,{ silent: true })
Use this way:
this.collection.reset(newCollection.toJSON(), {silent:true})
EDIT (Added example)
HTML
<button>change filter</button>
JS
var url1 = 'https://api.twitter.com/1/statuses/user_timeline.json?screen_name=vpetrychuk&count=9'
var url2 = 'https://api.twitter.com/1/statuses/user_timeline.json?screen_name=derickbailey&count=9'
var collection = new (Backbone.Collection.extend({
url : url1,
resetWithFilter : function(key, value) {
var query = {};
query[key] = value;
this.reset(this.where(query));
}
}));
// fetch initial data
collection.fetch({dataType:'jsonp'});
$(':button').on('click', function() {
// change url and fetch another data
collection.url = url2;
collection.fetch({dataType:'jsonp'}).done(function(response) {
console.log('items count before filter:', collection.length);
// now reset collection with selected filter
collection.resetWithFilter('id_str', '294429621640912896');
console.log('items count after filter:', collection.length)
});
});
Fiddle: http://jsfiddle.net/vpetrychuk/N4ZKm/

Resources