map.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /**
  2. * @ngdoc directive
  3. * @name map
  4. * @requires Attr2Options
  5. * @description
  6. * Implementation of {@link MapController}
  7. * Initialize a Google map within a `<div>` tag with given options and register events
  8. * It accepts children directives; marker, shape, or marker-clusterer
  9. *
  10. * It initialize map, children tags, then emits message as soon as the action is done
  11. * The message emitted from this directive is;
  12. * . mapInitialized
  13. *
  14. * Restrict To:
  15. * Element
  16. *
  17. * @param {Array} geo-fallback-center
  18. * The center of map incase geolocation failed. i.e. [0,0]
  19. * @param {String} init-event The name of event to initialize this map.
  20. * If this option is given, the map won't be initialized until the event is received.
  21. * To invoke the event, use $scope.$emit or $scope.$broacast.
  22. * i.e. <map init-event="init-map" ng-click="$emit('init-map')" center=... ></map>
  23. * @param {String} &lt;MapOption> Any Google map options,
  24. * https://developers.google.com/maps/documentation/javascript/reference?csw=1#MapOptions
  25. * @param {String} &lt;MapEvent> Any Google map events,
  26. * https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/map_events.html
  27. * @example
  28. * Usage:
  29. * <map MAP_OPTIONS_OR_MAP_EVENTS ..>
  30. * ... Any children directives
  31. * </map>
  32. *
  33. * Example:
  34. * <map center="[40.74, -74.18]" on-click="doThat()">
  35. * </map>
  36. *
  37. * <map geo-fallback-center="[40.74, -74.18]">
  38. * </map>
  39. */
  40. /*jshint -W030*/
  41. ngMap.directive('map', ['Attr2Options', '$timeout', function(Attr2Options, $timeout) {
  42. var parser = Attr2Options;
  43. function getStyle(el,styleProp)
  44. {
  45. if (el.currentStyle) {
  46. var y = el.currentStyle[styleProp];
  47. } else if (window.getComputedStyle) {
  48. var y = document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp);
  49. }
  50. return y;
  51. }
  52. return {
  53. restrict: 'AE',
  54. controller: ngMap.MapController,
  55. /**
  56. * Initialize map and events
  57. * @memberof map
  58. * @param {$scope} scope
  59. * @param {angular.element} element
  60. * @param {Hash} attrs
  61. * @ctrl {MapController} ctrl
  62. */
  63. link: function (scope, element, attrs, ctrl) {
  64. var orgAttrs = parser.orgAttributes(element);
  65. scope.google = google; //used by $scope.eval in Attr2Options to avoid eval()
  66. /**
  67. * create a new `div` inside map tag, so that it does not touch map element
  68. * http://stackoverflow.com/questions/20955356
  69. */
  70. var el = document.createElement("div");
  71. el.style.width = "100%";
  72. el.style.height = "100%";
  73. element.prepend(el);
  74. /**
  75. * if style is not given to the map element, set display and height
  76. */
  77. if (getStyle(element[0], 'display') != "block") {
  78. element.css('display','block');
  79. }
  80. if (getStyle(element[0], 'height').match(/^(0|auto)/)) {
  81. element.css('height','300px');
  82. }
  83. /**
  84. * initialize function
  85. */
  86. var initializeMap = function(mapOptions, mapEvents) {
  87. var map = new google.maps.Map(el, {});
  88. map.markers = {};
  89. map.shapes = {};
  90. /**
  91. * resize the map to prevent showing partially, in case intialized too early
  92. */
  93. $timeout(function() {
  94. google.maps.event.trigger(map, "resize");
  95. });
  96. /**
  97. * set options
  98. */
  99. mapOptions.zoom = mapOptions.zoom || 15;
  100. var center = mapOptions.center;
  101. if (!center) {
  102. mapOptions.center = new google.maps.LatLng(0,0);
  103. } else if (!(center instanceof google.maps.LatLng)) {
  104. delete mapOptions.center;
  105. Attr2Options.setDelayedGeoLocation(map, 'setCenter',
  106. center, {fallbackLocation: options.geoFallbackCenter});
  107. }
  108. map.setOptions(mapOptions);
  109. /**
  110. * set events
  111. */
  112. for (var eventName in mapEvents) {
  113. if (eventName) {
  114. google.maps.event.addListener(map, eventName, mapEvents[eventName]);
  115. }
  116. }
  117. /**
  118. * set observers
  119. */
  120. parser.observeAttrSetObj(orgAttrs, attrs, map);
  121. /**
  122. * set controller and set objects
  123. * so that map can be used by other directives; marker or shape
  124. * ctrl._objects are gathered when marker and shape are initialized before map is set
  125. */
  126. ctrl.map = map; /* so that map can be used by other directives; marker or shape */
  127. ctrl.addObjects(ctrl._objects);
  128. // /* providing method to add a marker used by user scope */
  129. // map.addMarker = ctrl.addMarker;
  130. /**
  131. * set map for scope and controller and broadcast map event
  132. * scope.map will be overwritten if user have multiple maps in a scope,
  133. * thus the last map will be set as scope.map.
  134. * however an `mapInitialized` event will be emitted every time.
  135. */
  136. scope.map = map;
  137. scope.map.scope = scope;
  138. //google.maps.event.addListenerOnce(map, "idle", function() {
  139. scope.$emit('mapInitialized', map);
  140. //});
  141. // the following lines will be deprecated on behalf of mapInitialized
  142. // to collect maps, we should use scope.maps in your own controller, i.e. MyCtrl
  143. scope.maps = scope.maps || {};
  144. scope.maps[options.id||Object.keys(scope.maps).length] = map;
  145. scope.$emit('mapsInitialized', scope.maps);
  146. }; // function initializeMap()
  147. /**
  148. * get map options and events
  149. */
  150. var filtered = parser.filter(attrs);
  151. var options = parser.getOptions(filtered, scope);
  152. var controlOptions = parser.getControlOptions(filtered);
  153. var mapOptions = angular.extend(options, controlOptions);
  154. var mapEvents = parser.getEvents(scope, filtered);
  155. console.log("filtered", filtered, "mapOptions", mapOptions, 'mapEvents', mapEvents);
  156. if (attrs.initEvent) { // allows controlled initialization
  157. scope.$on(attrs.initEvent, function() {
  158. !ctrl.map && initializeMap(mapOptions, mapEvents); // init if not done
  159. });
  160. } else {
  161. initializeMap(mapOptions, mapEvents);
  162. } // if
  163. }
  164. };
  165. }]);