info-window.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*jshint -W030*/
  2. /**
  3. * @ngdoc directive
  4. * @name info-window
  5. * @requires Attr2Options
  6. * @requires $compile
  7. * @description
  8. * Defines infoWindow and provides compile method
  9. *
  10. * Requires: map directive
  11. *
  12. * Restrict To: Element
  13. *
  14. * @param {Boolean} visible Indicates to show it when map is initialized
  15. * @param {Boolean} visible-on-marker Indicates to show it on a marker when map is initialized
  16. * @param {String} <InfoWindowOption> Any InfoWindow options,
  17. * https://developers.google.com/maps/documentation/javascript/reference?csw=1#InfoWindowOptions
  18. * @param {String} <InfoWindowEvent> Any InfoWindow events, https://developers.google.com/maps/documentation/javascript/reference
  19. * @example
  20. * Usage:
  21. * <map MAP_ATTRIBUTES>
  22. * <info-window id="foo" ANY_OPTIONS ANY_EVENTS"></info-window>
  23. * </map>
  24. *
  25. * Example:
  26. * <map center="41.850033,-87.6500523" zoom="3">
  27. * <info-window id="1" position="41.850033,-87.6500523" >
  28. * <div ng-non-bindable>
  29. * Chicago, IL<br/>
  30. * LatLng: {{chicago.lat()}}, {{chicago.lng()}}, <br/>
  31. * World Coordinate: {{worldCoordinate.x}}, {{worldCoordinate.y}}, <br/>
  32. * Pixel Coordinate: {{pixelCoordinate.x}}, {{pixelCoordinate.y}}, <br/>
  33. * Tile Coordinate: {{tileCoordinate.x}}, {{tileCoordinate.y}} at Zoom Level {{map.getZoom()}}
  34. * </div>
  35. * </info-window>
  36. * </map>
  37. */
  38. ngMap.directive('infoWindow', ['Attr2Options', '$compile', '$timeout', function(Attr2Options, $compile, $timeout) {
  39. var parser = Attr2Options;
  40. var getInfoWindow = function(options, events, element) {
  41. var infoWindow;
  42. /**
  43. * set options
  44. */
  45. if (options.position &&
  46. !(options.position instanceof google.maps.LatLng)) {
  47. var address = options.position;
  48. delete options.position;
  49. infoWindow = new google.maps.InfoWindow(options);
  50. var callback = function() {
  51. infoWindow.open(infoWindow.map);
  52. }
  53. parser.setDelayedGeoLocation(infoWindow, 'setPosition', address, {callback: callback});
  54. } else {
  55. infoWindow = new google.maps.InfoWindow(options);
  56. }
  57. /**
  58. * set events
  59. */
  60. if (Object.keys(events).length > 0) {
  61. console.log("infoWindow events", events);
  62. }
  63. for (var eventName in events) {
  64. if (eventName) {
  65. google.maps.event.addListener(infoWindow, eventName, events[eventName]);
  66. }
  67. }
  68. /**
  69. * set template ane template-relate functions
  70. * it must have a container element with ng-non-bindable
  71. */
  72. var template = element.html().trim();
  73. if (angular.element(template).length != 1) {
  74. throw "info-window working as a template must have a container";
  75. }
  76. infoWindow.__template = template.replace(/\s?ng-non-bindable[='"]+/,"");
  77. infoWindow.__compile = function(scope) {
  78. var el = $compile(infoWindow.__template)(scope);
  79. scope.$apply();
  80. infoWindow.setContent(el[0]);
  81. };
  82. infoWindow.__eval = function(event) {
  83. var template = infoWindow.__template;
  84. var _this = this;
  85. template = template.replace(/{{(event|this)[^;\}]+}}/g, function(match) {
  86. var expression = match.replace(/[{}]/g, "").replace("this.", "_this.");
  87. return eval(expression);
  88. });
  89. return template;
  90. };
  91. return infoWindow;
  92. };
  93. return {
  94. restrict: 'E',
  95. require: '^map',
  96. link: function(scope, element, attrs, mapController) {
  97. element.css('display','none');
  98. var orgAttrs = parser.orgAttributes(element);
  99. var filtered = parser.filter(attrs);
  100. var options = parser.getOptions(filtered, scope);
  101. var events = parser.getEvents(scope, filtered);
  102. console.log('infoWindow', 'options', options, 'events', events);
  103. var infoWindow = getInfoWindow(options, events, element);
  104. mapController.addObject('infoWindows', infoWindow);
  105. parser.observeAttrSetObj(orgAttrs, attrs, infoWindow); /* observers */
  106. // show InfoWindow when initialized
  107. if (infoWindow.visible) {
  108. //if (!infoWindow.position) { throw "Invalid position"; }
  109. scope.$on('mapInitialized', function(evt, map) {
  110. $timeout(function() {
  111. infoWindow.__template = infoWindow.__eval.apply(this, [evt]);
  112. infoWindow.__compile(scope);
  113. infoWindow.map = map;
  114. infoWindow.position && infoWindow.open(map);
  115. });
  116. });
  117. }
  118. // show InfoWindow on a marker when initialized
  119. if (infoWindow.visibleOnMarker) {
  120. scope.$on('mapInitialized', function(evt, map) {
  121. $timeout(function() {
  122. var markerId = infoWindow.visibleOnMarker;
  123. var marker = map.markers[markerId];
  124. if (!marker) throw "Invalid marker id";
  125. infoWindow.__template = infoWindow.__eval.apply(this, [evt]);
  126. infoWindow.__compile(scope);
  127. infoWindow.open(map, marker);
  128. });
  129. });
  130. }
  131. /**
  132. * provide showInfoWindow method to scope
  133. */
  134. scope.showInfoWindow = scope.showInfoWindow ||
  135. function(event, id, anchor) {
  136. var infoWindow = mapController.map.infoWindows[id],
  137. tempTemplate = infoWindow.__template; // set template in a temporary variable
  138. infoWindow.__template = infoWindow.__eval.apply(this, [event]);
  139. infoWindow.__compile(scope);
  140. if (anchor) {
  141. infoWindow.open(mapController.map, anchor);
  142. } else if (this.getPosition) {
  143. infoWindow.open(mapController.map, this);
  144. } else {
  145. infoWindow.open(mapController.map);
  146. }
  147. infoWindow.__template = tempTemplate; // reset template to the object
  148. };
  149. /**
  150. * provide hideInfoWindow method to scope
  151. */
  152. scope.hideInfoWindow = scope.hideInfoWindow ||
  153. function(event, id, anchor) {
  154. var infoWindow = mapController.map.infoWindows[id];
  155. infoWindow.__template = infoWindow.__eval.apply(this, [event]);
  156. infoWindow.__compile(scope);
  157. infoWindow.close();
  158. };
  159. } //link
  160. }; // return
  161. }]);// function