Google maps GeoJSON- toggle marker layers? - maps

I have some GeoJSON returned from a call to a PostGIS database. I'd like to be able to add a marker for each feature, and be able to toggle different types of marker/feature. Currently I'm using JavaScript to generate a marker for each feature, adding them to arrays according to type, and then going through the arrays setting show/hide as appropriate to toggle the 'layers'.
This works OK, but I'm wondering if the new GeoJSON functionality offers a better way to do this. As far as I can see though, all the features get added to the same datalayer and toggling sets of them would involve either setting styles or just replacing with new, pre-filtered GeoJSON.
So the question is is it possible to have more than one data layer, and easily add/remove them from the map or am I better off looking at something like OpenLayers?
EDIT: Bit more research shows it's quite straightforward.
For each type of feature in the feature collection that we want to toggle on, create a new Data object. Add all the relevant features to that data object.
var datalayer = new google.maps.Data();
datalayer.addGeoJson(feature);
datalayer.setMap(mainmap);
Then store each data object/feature type as a key-value pair. On toggle, pull out the relevant data object and setMap as appropriate:
var datalayer= featuretypesobj["feature type to toggle"];
datalayer.setMap(mymap); //or
datalayer.setMap(null);

You can also create separate layers
var layer_1 = new google.maps.Data();
var layer_2 = new google.maps.Data();
then populate it, e.g. with json data
layer_1.loadGeoJson('/path/to/data.json');
layer_2.loadGeoJson('/path/to/data2.json');
then add / remove them on the map
layer_1.setMap(map);
layer_2.setMap(map);
layer_1.setMap(null);

To Add:
var layer_1 = new google.maps.Data(); should be done inside map initialization function, as:
var map;
var data_layer_for_ramps;
function initialize() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: new google.maps.LatLng(-33.897907, 151.179138),//-33.8151,151.0032
mapTypeId: 'roadmap'
});
data_layer_for_ramps = new google.maps.Data();
}

Related

Angularjs - Charts.js: Same chart element doesn't redraw on other view

I am new to angularjs, trying to create my first directive. I am creating a directive to load Charts.js2.0(beta) into my application.
I have 2 views managed by angular-route, both html view has ng-included a html page that contains only charts-element.
The problem is the first page properly draws the chart, when i go to other view the charts div is loaded but charts is not re-drawn. And now if i go back to first view its blank.
Link to Plunker
What i am doing wrong? Is there any issue with my directive?
Thanks in advance.
There appears to be an issue with the Charts library modifying the existing object on the root scope, and thereby ignoring it forever afterward. I can't really trace down what is doing it, but here's a fix for you: http://plnkr.co/edit/jDQFV62FSeXAQJ6o7jE8
Here is what you had
scope.$watch('config', function(newVal) {
if(angular.isDefined(newVal)) {
if(charts) {
charts.destroy();
}
var ctx = element[0].getContext("2d");
charts = new Chart(ctx, scope.config);
//scope.$emit('create', charts);
}
});
Above, you can see that you're passing scope.config directly into the charts method. That appears to be modifying the data somehow, and since that's passed by reference, you're actually modifying $rootScope.sales.charts. If you copy that object and use it locally like below, you don't have that problem.
Here's how I fixed it.
scope.$watch('config', function(newVal) {
var config = angular.copy(scope.config);
if(angular.isDefined(newVal)) {
if(charts) {
charts.destroy();
}
var ctx = element[0].getContext("2d");
charts = new Chart(ctx, config);
//scope.$emit('create', charts);
}
});
You can see that instead of passing that object directly in, we use angular to make a copy (angular.copy()), and that's the object we pass in.
I think it has relation with the id of the canvas where you are drawing. I've had this problem too amd it was because i was using the same id for the canvas of two graphs in different views. Be sure that those ids are different and that the javasrcipt of each graph is in the controller of each view or in each view itself.
Taking a look at your pluker I see that you are using the same html for the graph and I guess that when angular moves from one of your views to the other thinks that the graph is already drawn. Differentiating two graphs will solve the problem. I don't know of there is any other approach that allows using the same html for the canvas of the graph.
Hope it helps you solve it

Angular.js view rendering (with a bit more than just showing the retrieved values)

I'm working on a view that allows user to type in the postcode and then it will give the location info about the postcode (lat, long, city name, etc), as well as marking the location on a map (using google map api).
For the postcod part, it is rather straight forward, I placed a few {{}} directives in the view and assign the corresponding values to the $scope in the controller. But when it comes to marking that location on the google map view, it gets a bit confusing. here is the sample code to mark a place in google map:
var containerID = 'map-container'; // id of a DIV
var lat = 50.2;
var lng = -3.6;
var container = document.getElementById(containerID);
var options = {
zoom: 15,
center: new google.maps.LatLng(lat, lng),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(container, options);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),
map: map,
title: markerTitle
});
As you can see, the code itself only involves rendering the map, and to me it should sit inside the view because a view is supposed to take the returned result from the controller and do whatever magic it wants to present that result. And since the code involves manipulating the DOM, which is another reason I don't think it should be in the controller.
But am I correct to make this assumption?
And even if i'm correct, how could I implement this?
You are right, DOM Manipulation should not be in the controller, but it shouldn't be in the view neither.
The Angular way would be to create a directive that handle all DOM Manipulation. This directive is independent and work alone, and is here to do the dirty job. Once you've created it, you add it in the view, and pass it the parameters from the controllers.
So the view display the element, the controllers set the model and values, and the directive handle DOM manipulation/graphic change,value processing ...etc.
Good news for you, I think that in your case the directive has already been made, you may want to take a look at : AngularUI GoogleMap Directive
Try writing your asynchronous codes inside.
$scope.$apply(function{
})

How to find Table and append a new record to its Store?

I need to update a Store based on some information that I have.
I have a table in the document, that uses some Store to keep data,
and in separate part of page I have a button that needs to add some information to the Store (and table). I got a bit confused, so, I just ask here all I need to know:
Which property in table configuration needs to be specified to locate table later?
Which call I need to make to find the table and locate its store?
How I can generate and append data to the table's existing store?
The "table" you are referring to is Grid in ExtJS terminology.
1. To get the grid for later use, you need a reference to that object. There are many ways in ExtJS to get hold of this reference.
Using Javascript Variables: Most simple way is to have a javascript variable that will hold the reference. This is usually done when the grid is created. For example:
var myGrid = Ext.create('Ext.grid.Panel', {
// All the configs...
});
You can use the myGrid variable to get access to the grid.
Using ComponentManager: When an ExtJS component is created, it gets registered with the component manager. You can always get hold of an ExtJS component from this register. The manager tracks each component with a unique id. To use this method, you will have to define a unique id for your grid component and later use the famous Ext.getCmp() method. Here is an example:
var myGrid = Ext.create('Ext.grid.Panel', {
id: 'myGrid', // Unique id for the grid
// All other configs...
});
Using this method is NOT the best practice.
Using itemId and Component Query: A better method than the above two; you can use the itemId config and ComponentQuery. ComponentQuery class provides a selector-based searching for Sencha Components analogous to DOM querying. Example:
var myGrid = Ext.create('Ext.grid.Panel', {
itemId: 'myGrid',
// All other configs...
});
And to get a reference, you may call the query() method from a container or use Ext.ComponentManager (this is global).
Accessing in MVC controller: If you are developing your application using MVC, you can make use of this method. A controller have reference array namely: refs. (Internally, the method makes use of ComponentQuery and selectors to access the component). Refer MVC guides and examples to see how this works..
2. Once you obtain the grid with any the above techniques, you can get the store simply by calling the method: getStore(). This returns the store object (Ext.data.Store). Example:
myStore = myGrid.getStore();
3. Refer the Ext.data.Store documentation. you can manipulate your grid's store using methods like add(),load(),remove() etc...
FYI.
It is not
Ext.Cmp()
it is
Ext.getCmp('myGrid')

Two-way binding from different qooxdoo classes

I'm trying to bind two sliders from two separate qooxdoo classes and am looking for an example. I was able to get the desired effect in the playground here:
http://tinyurl.com/7hlbwu6
// create two sliders
var slider1 = new qx.ui.form.Slider().set({minWidth:400});
var slider2 = new qx.ui.form.Slider().set({minWidth:400});
// create a controller and use the first slider as a model
var controller = new qx.data.controller.Object(slider1);
var controller2 = new qx.data.controller.Object(slider2);
// add the second slider as a target
controller.addTarget(slider2, "value", "value");
controller2.addTarget(slider1, "value", "value");
I'm pretty sure to do this I would have to go through the properties object, but first wanted to make sure that I'm on the right track so far with the logic. Thanks for any suggestions!
You don't need to use the controller. Every qooxdoo objects has the bind method, which can be used in both directions:
slider1.bind("value", slider2, "value");
slider2.bind("value", slider1, "value");
Thats basically it: http://tinyurl.com/7xy9mmv

Toggle KML overlay for Google Maps API v3 using checkbox

Does anyone have some sample code for toggling a KML overlay layer with a checkbox? I can get a kml layer on my map to toggle off when I uncheck the checkbox, but I can't get it to toggle back on. I've viewed all sorts of sample sites and code, but can't get this thing to work. The site in question is at www.fhitestsite.com/mdctest.
Thanks.
1) Your problem is that map var is not defined -
you defined var map inside a one function but trying to call it from other one. Define it outside of the function
...
var map;
var todayLayer;
var todayShown = 1;
var todayWdgt;
...
2) minor error. todayWdgt is NULL. Its just that you try to assign something that doesn't exist yet.
You should run this code after the document is ready.
todayWdgt = document.getElementById("todayBtn");
todayWdgt.checked = true;
Try using firebug.

Resources