dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #40971
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 20867: tracker/event-capture: google maps api is now loaded asynchronously
------------------------------------------------------------
revno: 20867
committer: Abyot Asalefew Gizaw <abyota@xxxxxxxxx>
branch nick: dhis2
timestamp: Fri 2015-10-23 17:42:36 +0200
message:
tracker/event-capture: google maps api is now loaded asynchronously
added:
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.map.directive.js
modified:
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/index.html
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/index.html
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/directives.js
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.directives.js
--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk
Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/index.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/index.html 2015-09-25 14:43:20 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/index.html 2015-10-23 15:42:36 +0000
@@ -6,14 +6,6 @@
<meta name="description" content="DHIS 2">
<meta name="keywords" content="DHIS 2">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-
- <script type="text/javascript">
- window.google = null;
- </script>
-
- <script type="text/javascript" src="https://maps.google.com/maps/api/js?v=3.19"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.map.textoverlay.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.map.contextmenu.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/jQuery/jquery.min.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/jQuery/ui/jquery-ui.min.js"></script>
@@ -70,9 +62,10 @@
<script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/angular-translate.min.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/select.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.directives.js"></script>
+ <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.map.directive.js"></script>
+ <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.services.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.filters.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.validations.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.services.js"></script>
+ <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.validations.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.controllers.js"></script>
<script type="text/javascript" src="scripts/app.js"></script>
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/index.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/index.html 2015-10-23 08:08:54 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/index.html 2015-10-23 15:42:36 +0000
@@ -8,18 +8,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <script type="text/javascript">
- window.google = null;
- </script>
-
- <script type="text/javascript" src="https://maps.google.com/maps/api/js?v=3.19"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.map.textoverlay.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.map.contextmenu.js"></script>
-
<script type="text/javascript" src="../dhis-web-commons/javascripts/jQuery/jquery.min.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/jQuery/ui/jquery-ui.min.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/jQuery/jquery.plugin.min.js"></script>
-
+ <script type="text/javascript" src="../dhis-web-commons/javascripts/jQuery/jquery.plugin.min.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/jQuery/calendars/jquery.calendars.min.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/jQuery/calendars/jquery.calendars.picker.min.js"></script>
@@ -82,6 +73,7 @@
<script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/angular-translate.min.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/ng-infinite-scroll.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.directives.js"></script>
+ <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.map.directive.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.services.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.validations.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.filters.js"></script>
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/directives.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/directives.js 2015-10-23 08:08:54 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/directives.js 2015-10-23 15:42:36 +0000
@@ -1,3 +1,5 @@
+/* global directive, selection, dhis2, angular */
+
'use strict';
/* Directives */
@@ -8,18 +10,18 @@
return {
restrict: 'A',
link: function (scope, element, attrs) {
-
+
selection.load();
$("#orgUnitTree").one("ouwtLoaded", function (event, ids, names) {
- if( dhis2.tc && dhis2.tc.metaDataCached ){
+ if (dhis2.tc && dhis2.tc.metaDataCached) {
$timeout(function () {
scope.treeLoaded = true;
scope.$apply();
});
- selection.responseReceived();
+ selection.responseReceived();
}
- else{
- console.log('Finished loading orgunit tree');
+ else {
+ console.log('Finished loading orgunit tree');
$("#orgUnitTree").addClass("disable-clicks"); //Disable ou selection until meta-data has downloaded
$timeout(function () {
scope.treeLoaded = true;
@@ -27,7 +29,7 @@
});
downloadMetaData();
}
- });
+ });
//listen to user selection, and inform angular
selection.setListenerFunction(setSelectedOu, true);
@@ -43,7 +45,7 @@
})
.directive('eventPaginator', function factory() {
-
+
return {
restrict: 'E',
controller: function ($scope, Paginator) {
@@ -53,16 +55,16 @@
};
})
-.directive('stringToNumber', function() {
- return {
- require: 'ngModel',
- link: function(scope, element, attrs, ngModel) {
- ngModel.$parsers.push(function(value) {
- return '' + value;
- });
- ngModel.$formatters.push(function(value) {
- return parseFloat(value, 10);
- });
- }
- }
+.directive('stringToNumber', function () {
+ return {
+ require: 'ngModel',
+ link: function (scope, element, attrs, ngModel) {
+ ngModel.$parsers.push(function (value) {
+ return '' + value;
+ });
+ ngModel.$formatters.push(function (value) {
+ return parseFloat(value, 10);
+ });
+ }
+ };
});
\ No newline at end of file
=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.directives.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.directives.js 2015-10-23 08:08:54 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.directives.js 2015-10-23 15:42:36 +0000
@@ -169,293 +169,6 @@
};
})
-.directive('d2GoogleMap', function ($http, $translate, CurrentSelection) {
- return {
- restrict: 'E',
- replace: true,
- template: '<div></div>',
- scope: {
- location: '='
- },
- link: function (scope, element, attrs) {
-
- CurrentSelection.setLocation(scope.location);
-
- var contextMenuDisplayed = false;
- var ouLevels = CurrentSelection.getOuLevels();
-
- //remove angular bootstrap ui modal draggable
- $(".modal-content").draggable({disabled: true});
-
- //get a default center
- var latCenter = 12.31, lngCenter = 51.48;
-
- //if there is any marker already - use it as center
- if (angular.isObject(scope.location)) {
- if (scope.location.lat && scope.location.lng) {
- latCenter = scope.location.lat;
- lngCenter = scope.location.lng;
- }
- }
-
- //default map configurations
- var mapOptions = {
- zoom: 4,
- center: new google.maps.LatLng(latCenter, lngCenter),
- mapTypeId: google.maps.MapTypeId.ROADMAP
- },
- featureStyle = {
- strokeWeight: 2,
- strokeOpacity: 0.4,
- fillOpacity: 0.2,
- fillColor: '#99cc99'
- };
-
- var map = new google.maps.Map(document.getElementById(attrs.id), mapOptions);
-
- var marker = new google.maps.Marker({
- map: map
- });
-
- if (angular.isObject(scope.location)) {
- if (scope.location.lat && scope.location.lng) {
- addMarker({lat: scope.location.lat, lng: scope.location.lng});
- }
- }
-
- var currentLayer = 0, currentGeojson, currentGeojsonFeatures;
-
- var contextMenuOptions = {};
- contextMenuOptions.classNames = {menu: 'map_context_menu', menuSeparator: 'map_context_menu_separator'};
-
- //create an array of MapContextMenuItem objects
- var menuItems = [];
- menuItems.push({className: 'map_context_menu_item', eventName: 'captureCoordinate', label: '<i class="fa fa-map-marker"></i> ' + $translate.instant('set_coordinate')});
- menuItems.push({});
- menuItems.push({className: 'map_context_menu_item', eventName: 'zoom_in', id: 'zoomIn', label: '<i class="fa fa-search-plus"></i> ' + $translate.instant('zoom_in')});
- menuItems.push({className: 'map_context_menu_item', eventName: 'zoom_out', id: 'zoomOut', label: '<i class="fa fa-search-minus"></i> ' + $translate.instant('zoom_out')});
- menuItems.push({});
- menuItems.push({className: 'map_context_menu_item', eventName: 'centerMap', label: '<i class="fa fa-crosshairs"></i> ' + $translate.instant('center_map')});
- contextMenuOptions.menuItems = menuItems;
- var mapContextMenu = new MapContextMenu(map, contextMenuOptions);
-
- function getGeoJsonByOuLevel(initialize, event, mode) {
- var url = '';
- if (initialize) {
- currentLayer = 0;
- url = '../api/organisationUnits.geojson?level=' + ouLevels[currentLayer].level;
- }
- else {
- if (mode === 'IN') {
- currentLayer++;
- url = '../api/organisationUnits.geojson?level=' + ouLevels[currentLayer].level + '&parent=' + event.feature.D;
- }
- if (mode === 'OUT') {
- currentLayer--;
- var parents = event.feature.k.parentGraph.substring(1, event.feature.k.parentGraph.length - 1).split('/');
- url = '../api/organisationUnits.geojson?level=' + ouLevels[currentLayer].level + '&parent=' + parents[parents.length - 2];
- }
- }
-
- $http.get(url).then(function (response) {
- currentGeojson = response.data;
- currentGeojsonFeatures = map.data.addGeoJson(currentGeojson);
-
- if (initialize) {
- google.maps.event.addListenerOnce(map, 'idle', function () {
- google.maps.event.trigger(map, 'resize');
- map.data.setStyle(featureStyle);
- centerMap();
- });
- }
- else {
- centerMap();
- }
- });
- }
-
- function addMarker(loc) {
- var latLng = new google.maps.LatLng(loc.lat, loc.lng);
- marker.setPosition(latLng);
- }
-
- function applyMarker(event) {
- addMarker({
- lat: event.latLng.lat(),
- lng: event.latLng.lng()
- });
-
- scope.location = {lat: event.latLng.lat(), lng: event.latLng.lng()};
- CurrentSelection.setLocation(scope.location);
- }
-
- function centerMap() {
- if (currentGeojson && currentGeojson.features) {
- var latLngBounds = getMapCenter(currentGeojson);
- map.fitBounds(latLngBounds);
- map.panToBounds(latLngBounds);
- }
- }
-
- var overLays = [];
- function getMapCenter(geoJson) {
- map.data.setStyle(featureStyle);
- if (!geoJson || !geoJson.features) {
- return;
- }
-
- var latLngBounds = new google.maps.LatLngBounds();
- overLays = [];
- angular.forEach(geoJson.features, function (feature) {
- var customTxt = '<div>' + feature.properties.name + '</div>';
- if (feature.geometry.type === 'MultiPolygon') {
- var polygonPoints = new google.maps.LatLngBounds();
- angular.forEach(feature.geometry.coordinates[0][0], function (coordinate) {
- latLngBounds.extend(new google.maps.LatLng(coordinate[1], coordinate[0]));
- polygonPoints.extend(new google.maps.LatLng(coordinate[1], coordinate[0]));
- });
- var txt = new Dhis2TextOverlay(polygonPoints.getCenter(), customTxt, "polygon-name", map);
- overLays.push(txt);
- }
- else if (feature.geometry.type === 'Point') {
- latLngBounds.extend(new google.maps.LatLng(feature.geometry.coordinates[1], feature.geometry.coordinates[0]));
- var txt = new Dhis2TextOverlay(new google.maps.LatLng(feature.geometry.coordinates[1], feature.geometry.coordinates[0]), customTxt, "polygon-name", map);
- overLays.push(txt);
- }
- });
-
- return latLngBounds;
- }
-
- function initializeMap() {
- getGeoJsonByOuLevel(true, null);
- }
-
- function zoomMap(event, mode) {
-
- for (var i = 0; i < currentGeojsonFeatures.length; i++) {
- map.data.remove(currentGeojsonFeatures[i]);
- }
-
- for (var i = 0; i < overLays.length; i++) {
- overLays[i].setMap(null);
- }
-
- getGeoJsonByOuLevel(false, event, mode);
- }
-
- function enableDisableZoom() {
- if (currentLayer >= ouLevels.length - 1) {
- $("#zoomIn").addClass('disabled-context-menu-item');
- $("#zoomIn").removeClass('mouse-pointer');
- $('#zoomIn').attr('disabled', "disabled");
- } else {
- $("#zoomIn").removeClass('disabled-context-menu-item');
- $("#zoomIn").addClass('enable-context-menu-item');
- $('#zoomIn').attr('disabled', "");
- }
- if (currentLayer === 0) {
- $("#zoomOut").addClass('disabled-context-menu-item');
- $("#zoomOut").removeClass('enable-context-menu-item');
- $('#zoomOut').attr('disabled', "disabled");
- }
- else {
- $("#zoomOut").removeClass('disabled-context-menu-item');
- $("#zoomOut").addClass('enable-context-menu-item');
- $('#zoomIn').attr('disabled', "");
- }
- }
-
- function showHideContextMenu(event, allowDisable) {
- if (contextMenuDisplayed) {
- mapContextMenu.hide();
- contextMenuDisplayed = false;
- }
- else {
- mapContextMenu.show(event);
- if (allowDisable) {
- enableDisableZoom();
- }
- }
- }
-
- //get lable for current polygon
- map.data.addListener('mouseover', function (e) {
- $("#polygon-label").text(e.feature.k.name);
- map.data.revertStyle();
- map.data.overrideStyle(e.feature, {fillOpacity: 0.2});
- });
-
- //remove polygon label
- map.data.addListener('mouseout', function () {
- $("#polygon-label").text('');
- map.data.revertStyle();
- });
-
- //context menu based on polygons assigned to orgunits
- map.data.addListener('rightclick', function (e) {
- showHideContextMenu(e, true);
- });
-
- map.data.addListener('click', function (e) {
- showHideContextMenu(e, true);
- });
-
- //context menu based on points assigned to orgunits
- google.maps.event.addListener(marker, 'rightclick', function (e) {
- showHideContextMenu(e, true);
- });
-
- google.maps.event.addListener(marker, 'click', function (e) {
- showHideContextMenu(e, true);
- });
-
- //context menu anywhere in the map - incase no polygons are defined
- google.maps.event.addListener(map, 'rightclick', function (e) {
- showHideContextMenu(e, false);
- });
-
- google.maps.event.addListener(map, 'click', function (e) {
- showHideContextMenu(e, false);
- });
-
- //listen for the clicks on mapContextMenu
- google.maps.event.addListener(mapContextMenu, 'menu_item_selected', function (e, latLng, eventName) {
- switch (eventName) {
- case 'zoom_in':
- if (e.feature) {
- zoomMap(e, 'IN');
- }
- else {
- map.setZoom(map.getZoom() + 1);
- }
-
- break;
- case 'zoom_out':
- if (e.feature) {
- zoomMap(e, 'OUT');
- }
- else {
- map.setZoom(map.getZoom() - 1);
- }
-
- break;
- case 'centerMap':
- contextMenuDisplayed = true;
- map.panTo(latLng);
- break;
- case 'captureCoordinate':
- contextMenuDisplayed = true;
- applyMarker(e);
- break;
- }
- });
-
- initializeMap();
- }
- };
-})
-
.directive('d2CustomForm', function ($compile) {
return{
restrict: 'E',
=== added file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.map.directive.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.map.directive.js 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.map.directive.js 2015-10-23 15:42:36 +0000
@@ -0,0 +1,557 @@
+d2Directives.directive('d2GoogleMap', function ($http, $translate, $q, $window, CurrentSelection) {
+
+ function lazyLoadApi() {
+
+ var deferred = $q.defer();
+ $window.initMap = function() {
+ deferred.resolve();
+ };
+
+ var script = document.createElement('script');
+ script.src = 'https://maps.google.com/maps/api/js?callback=initMap';
+ document.body.appendChild(script);
+ return deferred.promise;
+ }
+
+ return {
+ restrict: 'E',
+ replace: true,
+ template: '<div></div>',
+ scope: {
+ location: '='
+ },
+ link: function (scope, element, attrs) {
+
+ function renderMap(){
+
+ // https://developers.google.com/maps/documentation/javascript/customoverlays
+ /** @constructor */
+ function Dhis2TextOverlay(pos, txt, cls, map) {
+
+ // Initialize properties.
+ this.pos = pos;
+ this.txt_ = txt;
+ this.cls_ = cls;
+ this.map_ = map;
+
+ // Div to contain text
+ this.div_ = null;
+
+ // Explicitly call setMap() on this overlay
+ this.setMap(map);
+ }
+
+ Dhis2TextOverlay.prototype = new google.maps.OverlayView();
+
+
+ /**
+ * onAdd is called when the map's panes are ready and the overlay has been
+ * added to the map.
+ */
+ Dhis2TextOverlay.prototype.onAdd = function () {
+
+ // Create the DIV and set some basic attributes.
+ var div = document.createElement('DIV');
+ div.className = this.cls_;
+ div.innerHTML = this.txt_;
+
+ // Set the overlay's div_ property to this DIV
+ this.div_ = div;
+ var overlayProjection = this.getProjection();
+ var position = overlayProjection.fromLatLngToDivPixel(this.pos);
+ div.style.left = position.x + 'px';
+ div.style.top = position.y + 'px';
+
+ // Add the element to the "overlayLayer" pane.
+ var panes = this.getPanes();
+ panes.floatPane.appendChild(div);
+ };
+
+ Dhis2TextOverlay.prototype.draw = function () {
+
+ // We use the south-west and north-east
+ // coordinates of the overlay to peg it to the correct position and size.
+ // To do this, we need to retrieve the projection from the overlay.
+ var overlayProjection = this.getProjection();
+
+ // Retrieve the southwest and northeast coordinates of this overlay
+ // in latlngs and convert them to pixels coordinates.
+ // We'll use these coordinates to resize the DIV.
+ var position = overlayProjection.fromLatLngToDivPixel(this.pos);
+
+ // Resize the div to fit the indicated dimensions.
+ var div = this.div_;
+ div.style.left = position.x + 'px';
+ div.style.top = position.y + 'px';
+ };
+
+ // The onRemove() method will be called automatically from the API if
+ // we ever set the overlay's map property to 'null'
+ Dhis2TextOverlay.prototype.onRemove = function () {
+ this.div_.parentNode.removeChild(this.div_);
+ this.div_ = null;
+ };
+
+ // Set the visibility to 'hidden' or 'visible'.
+ Dhis2TextOverlay.prototype.hide = function () {
+ if (this.div_) {
+ this.div_.style.visibility = "hidden";
+ }
+ };
+
+ Dhis2TextOverlay.prototype.show = function () {
+ if (this.div_) {
+ this.div_.style.visibility = "visible";
+ }
+ };
+
+ Dhis2TextOverlay.prototype.toggle = function () {
+ if (this.div_) {
+ if (this.div_.style.visibility === "hidden") {
+ this.show();
+ }
+ else {
+ this.hide();
+ }
+ }
+ };
+
+ // Detach the map from the DOM via toggleDOM().
+ // Note that if we later reattach the map, it will be visible again,
+ // because the containing <div> is recreated in the overlay's onAdd() method.
+ Dhis2TextOverlay.prototype.toggleDOM = function () {
+ if (this.getMap()) {
+ this.setMap(null);
+ }
+ else {
+ this.setMap(this.map_);
+ }
+ };
+
+
+ /*
+ MapContextMenu v1.0
+
+ A context menu for Google Maps API v3
+ http://code.martinpearman.co.uk/googlemapsapi/contextmenu/
+
+ Copyright Martin Pearman
+ Last updated 21st November 2011
+
+ developer@xxxxxxxxxxxxxxxxxxx
+
+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+ function MapContextMenu(map, options){
+ options=options || {};
+
+ this.setMap(map);
+
+ this.classNames_=options.classNames || {};
+ this.map_=map;
+ this.mapDiv_=map.getDiv();
+ this.menuItems_=options.menuItems || [];
+ this.pixelOffset=options.pixelOffset || new google.maps.Point(10, -5);
+ }
+
+ MapContextMenu.prototype=new google.maps.OverlayView();
+
+ MapContextMenu.prototype.draw=function(){
+ if(this.isVisible_){
+ var mapSize=new google.maps.Size(this.mapDiv_.offsetWidth, this.mapDiv_.offsetHeight);
+ var menuSize=new google.maps.Size(this.menu_.offsetWidth, this.menu_.offsetHeight);
+ var mousePosition=this.getProjection().fromLatLngToDivPixel(this.position_);
+
+ var left=mousePosition.x;
+ var top=mousePosition.y;
+
+ if(mousePosition.x>mapSize.width-menuSize.width-this.pixelOffset.x){
+ left=left-menuSize.width-this.pixelOffset.x;
+ } else {
+ left+=this.pixelOffset.x;
+ }
+
+ if(mousePosition.y>mapSize.height-menuSize.height-this.pixelOffset.y){
+ top=top-menuSize.height-this.pixelOffset.y;
+ } else {
+ top+=this.pixelOffset.y;
+ }
+
+ this.menu_.style.left=left+'px';
+ this.menu_.style.top=top+'px';
+ }
+ };
+
+ MapContextMenu.prototype.getVisible=function(){
+ return this.isVisible_;
+ };
+
+ MapContextMenu.prototype.hide=function(){
+ if(this.isVisible_){
+ this.menu_.style.display='none';
+ this.isVisible_=false;
+ }
+ };
+
+ MapContextMenu.prototype.onAdd=function(){
+ function createMenuItem(values){
+ var menuItem=document.createElement('div');
+ menuItem.innerHTML=values.label;
+ if(values.className){
+ menuItem.className=values.className;
+ }
+ if(values.id){
+ menuItem.id=values.id;
+ }
+ menuItem.style.cssText='white-space:nowrap; font-size: 12pt;';
+ menuItem.onclick=function(){
+ google.maps.event.trigger($this, 'menu_item_selected', $this.event_, $this.position_, values.eventName);
+ };
+ return menuItem;
+ }
+ function createMenuSeparator(){
+ var menuSeparator=document.createElement('div');
+ if($this.classNames_.menuSeparator){
+ menuSeparator.className=$this.classNames_.menuSeparator;
+ }
+ return menuSeparator;
+ }
+ var $this=this; // used for closures
+
+ var menu=document.createElement('div');
+ if(this.classNames_.menu){
+ menu.className=this.classNames_.menu;
+ }
+ menu.style.cssText='display:none; position:absolute';
+
+ for(var i=0, j=this.menuItems_.length; i<j; i++){
+ if(this.menuItems_[i].label && this.menuItems_[i].eventName){
+ menu.appendChild(createMenuItem(this.menuItems_[i]));
+ } else {
+ menu.appendChild(createMenuSeparator());
+ }
+ }
+
+ delete this.classNames_;
+ delete this.menuItems_;
+
+ this.isVisible_=false;
+ this.menu_=menu;
+ this.position_=new google.maps.LatLng(0, 0);
+
+ google.maps.event.addListener(this.map_, 'click', function(mouseEvent){
+ $this.hide();
+ });
+
+ this.getPanes().floatPane.appendChild(menu);
+ };
+
+ MapContextMenu.prototype.onRemove=function(){
+ this.menu_.parentNode.removeChild(this.menu_);
+ delete this.mapDiv_;
+ delete this.menu_;
+ delete this.position_;
+ };
+
+ MapContextMenu.prototype.show=function(e){
+ if(!this.isVisible_){
+ this.menu_.style.display='block';
+ this.isVisible_=true;
+ }
+ this.position_=e.latLng;
+ this.event_=e;
+ this.draw();
+ };
+
+
+ CurrentSelection.setLocation(scope.location);
+
+ var contextMenuDisplayed = false;
+ var ouLevels = CurrentSelection.getOuLevels();
+
+ //remove angular bootstrap ui modal draggable
+ $(".modal-content").draggable({disabled: true});
+
+ //get a default center
+ var latCenter = 12.31, lngCenter = 51.48;
+
+ //if there is any marker already - use it as center
+ if (angular.isObject(scope.location)) {
+ if (scope.location.lat && scope.location.lng) {
+ latCenter = scope.location.lat;
+ lngCenter = scope.location.lng;
+ }
+ }
+
+ //default map configurations
+ var mapOptions = {
+ zoom: 4,
+ center: new google.maps.LatLng(latCenter, lngCenter),
+ mapTypeId: google.maps.MapTypeId.ROADMAP
+ },
+ featureStyle = {
+ strokeWeight: 2,
+ strokeOpacity: 0.4,
+ fillOpacity: 0.2,
+ fillColor: '#99cc99'
+ };
+
+ var map = new google.maps.Map(document.getElementById(attrs.id), mapOptions);
+
+ var marker = new google.maps.Marker({
+ map: map
+ });
+
+ if (angular.isObject(scope.location)) {
+ if (scope.location.lat && scope.location.lng) {
+ addMarker({lat: scope.location.lat, lng: scope.location.lng});
+ }
+ }
+
+ var currentLayer = 0, currentGeojson, currentGeojsonFeatures;
+
+ var contextMenuOptions = {};
+ contextMenuOptions.classNames = {menu: 'map_context_menu', menuSeparator: 'map_context_menu_separator'};
+
+ //create an array of MapContextMenuItem objects
+ var menuItems = [];
+ menuItems.push({className: 'map_context_menu_item', eventName: 'captureCoordinate', label: '<i class="fa fa-map-marker"></i> ' + $translate.instant('set_coordinate')});
+ menuItems.push({});
+ menuItems.push({className: 'map_context_menu_item', eventName: 'zoom_in', id: 'zoomIn', label: '<i class="fa fa-search-plus"></i> ' + $translate.instant('zoom_in')});
+ menuItems.push({className: 'map_context_menu_item', eventName: 'zoom_out', id: 'zoomOut', label: '<i class="fa fa-search-minus"></i> ' + $translate.instant('zoom_out')});
+ menuItems.push({});
+ menuItems.push({className: 'map_context_menu_item', eventName: 'centerMap', label: '<i class="fa fa-crosshairs"></i> ' + $translate.instant('center_map')});
+ contextMenuOptions.menuItems = menuItems;
+ var mapContextMenu = new MapContextMenu(map, contextMenuOptions);
+
+ function getGeoJsonByOuLevel(initialize, event, mode) {
+ var url = '';
+ if (initialize) {
+ currentLayer = 0;
+ url = '../api/organisationUnits.geojson?level=' + ouLevels[currentLayer].level;
+ }
+ else {
+ if (mode === 'IN') {
+ currentLayer++;
+ url = '../api/organisationUnits.geojson?level=' + ouLevels[currentLayer].level + '&parent=' + event.feature.getId();
+ }
+ if (mode === 'OUT') {
+ currentLayer--;
+ var parents = event.feature.getProperty('parentGraph').substring(1, event.feature.getProperty('parentGraph').length - 1).split('/');
+ url = '../api/organisationUnits.geojson?level=' + ouLevels[currentLayer].level + '&parent=' + parents[parents.length - 2];
+ }
+ }
+
+ $http.get(url).then(function (response) {
+ currentGeojson = response.data;
+ currentGeojsonFeatures = map.data.addGeoJson(currentGeojson);
+
+ if (initialize) {
+ google.maps.event.addListenerOnce(map, 'idle', function () {
+ google.maps.event.trigger(map, 'resize');
+ map.data.setStyle(featureStyle);
+ centerMap();
+ });
+ }
+ else {
+ centerMap();
+ }
+ });
+ }
+
+ function addMarker(loc) {
+ var latLng = new google.maps.LatLng(loc.lat, loc.lng);
+ marker.setPosition(latLng);
+ }
+
+ function applyMarker(event) {
+ addMarker({
+ lat: event.latLng.lat(),
+ lng: event.latLng.lng()
+ });
+
+ scope.location = {lat: event.latLng.lat(), lng: event.latLng.lng()};
+ CurrentSelection.setLocation(scope.location);
+ }
+
+ function centerMap() {
+ if (currentGeojson && currentGeojson.features) {
+ var latLngBounds = getMapCenter(currentGeojson);
+ map.fitBounds(latLngBounds);
+ map.panToBounds(latLngBounds);
+ }
+ }
+
+ var overLays = [];
+ function getMapCenter(geoJson) {
+ map.data.setStyle(featureStyle);
+ if (!geoJson || !geoJson.features) {
+ return;
+ }
+
+ var latLngBounds = new google.maps.LatLngBounds();
+ overLays = [];
+ angular.forEach(geoJson.features, function (feature) {
+ var customTxt = '<div>' + feature.properties.name + '</div>';
+ if (feature.geometry.type === 'MultiPolygon') {
+ var polygonPoints = new google.maps.LatLngBounds();
+ angular.forEach(feature.geometry.coordinates[0][0], function (coordinate) {
+ latLngBounds.extend(new google.maps.LatLng(coordinate[1], coordinate[0]));
+ polygonPoints.extend(new google.maps.LatLng(coordinate[1], coordinate[0]));
+ });
+ var txt = new Dhis2TextOverlay(polygonPoints.getCenter(), customTxt, "polygon-name", map);
+ overLays.push(txt);
+ }
+ else if (feature.geometry.type === 'Point') {
+ latLngBounds.extend(new google.maps.LatLng(feature.geometry.coordinates[1], feature.geometry.coordinates[0]));
+ var txt = new Dhis2TextOverlay(new google.maps.LatLng(feature.geometry.coordinates[1], feature.geometry.coordinates[0]), customTxt, "polygon-name", map);
+ overLays.push(txt);
+ }
+ });
+
+ return latLngBounds;
+ }
+
+ function initializeMap() {
+ getGeoJsonByOuLevel(true, null);
+ }
+
+ function zoomMap(event, mode) {
+
+ for (var i = 0; i < currentGeojsonFeatures.length; i++) {
+ map.data.remove(currentGeojsonFeatures[i]);
+ }
+
+ for (var i = 0; i < overLays.length; i++) {
+ overLays[i].setMap(null);
+ }
+
+ getGeoJsonByOuLevel(false, event, mode);
+ }
+
+ function enableDisableZoom() {
+ if (currentLayer >= ouLevels.length - 1) {
+ $("#zoomIn").addClass('disabled-context-menu-item');
+ $("#zoomIn").removeClass('mouse-pointer');
+ $('#zoomIn').attr('disabled', "disabled");
+ } else {
+ $("#zoomIn").removeClass('disabled-context-menu-item');
+ $("#zoomIn").addClass('enable-context-menu-item');
+ $('#zoomIn').attr('disabled', "");
+ }
+ if (currentLayer === 0) {
+ $("#zoomOut").addClass('disabled-context-menu-item');
+ $("#zoomOut").removeClass('enable-context-menu-item');
+ $('#zoomOut').attr('disabled', "disabled");
+ }
+ else {
+ $("#zoomOut").removeClass('disabled-context-menu-item');
+ $("#zoomOut").addClass('enable-context-menu-item');
+ $('#zoomIn').attr('disabled', "");
+ }
+ }
+
+ function showHideContextMenu(event, allowDisable) {
+ if (contextMenuDisplayed) {
+ mapContextMenu.hide();
+ contextMenuDisplayed = false;
+ }
+ else {
+ mapContextMenu.show(event);
+ if (allowDisable) {
+ enableDisableZoom();
+ }
+ }
+ }
+
+ //get lable for current polygon
+ map.data.addListener('mouseover', function (e) {
+ $("#polygon-label").text(e.feature.getProperty('name'));
+ map.data.revertStyle();
+ map.data.overrideStyle(e.feature, {fillOpacity: 0.2});
+ });
+
+ //remove polygon label
+ map.data.addListener('mouseout', function () {
+ $("#polygon-label").text('');
+ map.data.revertStyle();
+ });
+
+ //context menu based on polygons assigned to orgunits
+ map.data.addListener('rightclick', function (e) {
+ showHideContextMenu(e, true);
+ });
+
+ map.data.addListener('click', function (e) {
+ showHideContextMenu(e, true);
+ });
+
+ //context menu based on points assigned to orgunits
+ google.maps.event.addListener(marker, 'rightclick', function (e) {
+ showHideContextMenu(e, true);
+ });
+
+ google.maps.event.addListener(marker, 'click', function (e) {
+ showHideContextMenu(e, true);
+ });
+
+ //context menu anywhere in the map - incase no polygons are defined
+ google.maps.event.addListener(map, 'rightclick', function (e) {
+ showHideContextMenu(e, false);
+ });
+
+ google.maps.event.addListener(map, 'click', function (e) {
+ showHideContextMenu(e, false);
+ });
+
+ //listen for the clicks on mapContextMenu
+ google.maps.event.addListener(mapContextMenu, 'menu_item_selected', function (e, latLng, eventName) {
+ switch (eventName) {
+ case 'zoom_in':
+ if (e.feature) {
+ zoomMap(e, 'IN');
+ }
+ else {
+ map.setZoom(map.getZoom() + 1);
+ }
+
+ break;
+ case 'zoom_out':
+ if (e.feature) {
+ zoomMap(e, 'OUT');
+ }
+ else {
+ map.setZoom(map.getZoom() - 1);
+ }
+
+ break;
+ case 'centerMap':
+ contextMenuDisplayed = true;
+ map.panTo(latLng);
+ break;
+ case 'captureCoordinate':
+ contextMenuDisplayed = true;
+ applyMarker(e);
+ break;
+ }
+ });
+
+ initializeMap();
+ }
+ if ($window.google && $window.google.maps) {
+ renderMap();
+ } else {
+ lazyLoadApi().then(function () {
+ renderMap();
+ }, function () {
+ console.log('GM loading failed.');
+ });
+ }
+ }
+ };
+})
\ No newline at end of file