PageSourceSearch

https://www.mileone.com/v9/media/js/ddc/v1/modules/googlemap.js

js mileone.com collected 2026-09-25 05:34:25 UTC 20,460 bytes, 522 lines download raw bytes

1/*jslint regexp: true, browser: true, confusion: true, unparam: true, sloppy: true, white: true, forin: true, nomen: true, plusplus: true, maxerr: 50, indent: 4 */
2
3(function() {
4	var window = this,
5		$ = window.jQuery,
6		DDC = (window.DDC = (window.DDC || {})),
7		hide = false,
8		show = true,
9		mapCoordsList = [];
10
11	DDC.modules.googleMap.refresh = function() {
12		var google = window.google;
13		DDC.modules.googleMap["previous"] = DDC.modules.googleMap["previous"] || {};
14		DDC.modules.googleMap["mapNumber"] = DDC.modules.googleMap["mapNumber"] || 0;
15		//use a data attr flag on this map instance to check if it has already be initialized
16		if (typeof google === 'object' && google.hasOwnProperty('load')) {
17			if (!$(this).data('google-map-initialized')) {
18				$(this).data('google-map-initialized', true);
19				var mapsApiKey = DDC.siteSettings && DDC.siteSettings.googleMapsApiKey ? DDC.siteSettings.googleMapsApiKey : '';
20				if (!mapsApiKey) {
21					DDC.log('Google Maps API key not configured');
22					return;
23				}
24
25				google.load('maps', '3', {
26					other_params: 'language=' + DDC.getLang() + '&key=' + mapsApiKey + '&libraries=places',
27					callback: function () {
28						initGoogleMap()
29					}
30				});
31			} else {
32				initGoogleMap()
33			}
34		}
35		// end map exists check
36		initGoogleMap = function() {
37			$(document).trigger("google-maps-initialized");
38			DDC.googleMaps = DDC.googleMaps || [];
39			DDC.googleMapsMarkers = DDC.googleMapsMarkers || [];
40			
41			var getEvData = function() {
42				var data = [];
43				$.ajax({
44					url: "/static/assets/map-locations/ev-charging-map-data.json",
45					dataType: 'json', 
46					async: false,
47					success: function(result){
48						data.push(result['entries'])
49					},
50					error: function(xhr) {
51						console.log(xhr.responseText)
52					},
53				  });
54				  return data[0]
55			}
56			
57			var myOptions = {},
58				mapEl,
59				map = {},
60				ignoreBounds = true, // Ignores the mapBounds based on multiple markers. Fix for multiple dealerships in same location.
61				directionsService = new google.maps.DirectionsService(),
62				geocoder = new google.maps.Geocoder(),
63				isCoord = function(a) {
64					return $.isArray(a) && (a.length === 2) && !isNaN(a[0]) && !isNaN(a[1]);
65				},
66				isLatLng = function(a) {
67					return a instanceof google.maps.LatLng;
68				},
69				isPoint = function(a) {
70					return isLatLng(a) || isCoord(a);
71				},
72				containsLatLng = function(list, point) {
73					var res = false;
74
75					if (list && point) {
76						res = !!$.grep(list, function(e, i) {
77							return list[i].equals(point);
78						}).length;
79					}
80
81					return res;
82				},
83				getMapBounds = function(list) {
84					var res = false;
85
86					// filter out any values that can't be calculated
87					list = $.grep(list, isPoint);
88
89					// convert all coords to LatLng points
90					$.each(list, function(i, v) {
91						if (isCoord(v)) {
92							list[i] = new google.maps.LatLng(v[0], v[1]);
93						}
94					});
95
96					if (list.length) {
97						res = new google.maps.LatLngBounds(list[0], list[0]);
98						for (i = 1; i < list.length; i++) {
99							res.extend(list[i]);
100							if (!list[i].equals(list[i - 1])) {
101								ignoreBounds = false; // use google maps bounds based on multiple markers
102							}
103						}
104					}
105					return res;
106				},
107				coords = function() {
108					this.list = [],
109						this.getList = function() {
110							return $.grep(this.list, function(i) { if (i) { return i } });
111						},
112						this.addToList = function(latlng, i) {
113							if (isLatLng(latlng) && !containsLatLng(this.list)) {
114								this.list[i] = latlng;
115							} else {
116								this.list[i] = '';
117							}
118						},
119						this.addCoords = function(coordsArray, map, mapCoords, it) {
120							var self = this,
121								geocodesOutstanding = coordsArray.length;
122
123							if (geocodesOutstanding) {
124								$.each(coordsArray, function(i, v) {
125									if (v && (!$.isArray(v) || v.length !== 2)) {
126										v = v.toString();
127
128										// geocode if marker isn't a lat/lng coord
129										geocoder.geocode({'address': v}, function(results, status) {
130											if (status === google.maps.GeocoderStatus.OK) {
131												// LatLng object returned
132												self.addToList(results[0].geometry.location, i);
133											}
134
135											if (!--geocodesOutstanding) {
136												self.pushCoords(map, self, it);
137											}
138										});
139									} else {
140										if (isCoord(v)) {
141											// convert lat/lng coords into LatLng object
142											self.addToList(new google.maps.LatLng(v[0], v[1]), i);
143
144											if (!--geocodesOutstanding) {
145												self.pushCoords(map, self, it);
146											}
147										}
148									}
149								});
150							}
151						},
152						this.pushCoords = function(map, self, it) {
153							mapCoordsList.push(self);
154							initializeMap(it);
155							map.data('google-maps-initialized', true);
156						},
157						this.getCenter = function() {
158							var res = this.getBounds(this.list);
159
160							if (res) {
161								res = res.getCenter();
162							}
163
164							return res;
165						},
166						this.getBounds = function() {
167							return getMapBounds(this.list);
168						}
169				},
170				initializeMap = function(x) {
171					var currentCoords = mapCoordsList[x],
172						currentCoordList = currentCoords.getList(),
173						scrollWheel = myOptions.scrollWheel != undefined;
174
175					currentCoords.center = currentCoords.getCenter();
176
177					if (currentCoords.center) {
178						myOptions.center = currentCoords.center;
179
180						map[x] = new google.maps.Map(mapEl[0], {
181							center: myOptions.center,
182							zoom: myOptions.zoom,
183							mapTypeId: myOptions.mapTypeId,
184							streetViewControl: false,
185							navigationControl: true,
186							mapTypeControl: true,
187							scrollwheel: scrollWheel,
188							originalCenter: myOptions.center,
189							styles: DDC.checkNested(DDC, 'WidgetData', 'map_dynamic', 'styles') ? DDC.WidgetData.map_dynamic.styles : []
190						});
191
192						DDC.googleMaps.push(map[x]);
193
194						// Emit map interaction signals for ws-tracking to consume
195						// (mirrors the marker-clicked-google-maps trigger below).
196						// ws-tracking turns these into ddc.map.* events and the
197						// tagging layer maps them per the client spec. We pass the
198						// map instance so ws-tracking can resolve the widget via
199						// map.getDiv().
200						(function(mapInstance) {
201							// pan: user drag only. Programmatic panTo/fitBounds do n
201ot
202							// fire dragend, so no init-time false positives.
203							google.maps.event.addListener(mapInstance, 'dragend', function() {
204								$(document).trigger('map-panned-google-maps', mapInstance);
205							});
206
207							// zoom and view-type (Map/Satellite/Terrain) both fire during
208							// the initial fitBounds/type set, so wait for the map's first
209							// idle before listening. Debounce zoom so a single
210							// scroll-wheel/pinch gesture emits once; view-type is discrete.
211							google.maps.event.addListenerOnce(mapInstance, 'idle', function() {
212								var zoomTimer;
213								google.maps.event.addListener(mapInstance, 'zoom_changed', function() {
214									clearTimeout(zoomTimer);
215									zoomTimer = setTimeout(function() {
216										$(document).trigger('map-zoomed-google-maps', mapInstance);
217									}, 250);
218								});
219								google.maps.event.addListener(mapInstance, 'maptypeid_changed', function() {
220									$(document).trigger('map-viewchanged-google-maps', mapInstance);
221								});
222							});
223
224							// fullscreen: Google requests fullscreen on the map div. Both
225							// entering and exiting are interactions. fullscreenchange is a
226							// document event, so attribute it to this map by its div and
227							// track whether this map was the one in fullscreen for the exit.
228							document.addEventListener('fullscreenchange', function() {
229								var fsEl = document.fullscreenElement,
230									div = mapInstance.getDiv();
231								if (fsEl && (fsEl === div || div.contains(fsEl))) {
232									mapInstance.wsWasFullscreen = true;
233									$(document).trigger('map-fullscreen-google-maps', mapInstance);
234								} else if (!fsEl && mapInstance.wsWasFullscreen) {
235									mapInstance.wsWasFullscreen = false;
236									$(document).trigger('map-fullscreen-google-maps', mapInstance);
237								}
238							});
239						})(map[x]);
240
241						if (myOptions && myOptions.circleAddress) {
242							if (myOptions.circleAddress.toString().length === 4) {
243								myOptions.circleAddress = '0' + myOptions.circleAddress.toString();
244							}
245
246							geocoder.geocode({'address': myOptions.data.circleAddress.toString()}, function(results, status) {
247								var radius = myOptions.data.circleRadius;
248
249								if (radius && (myOptions.circleRadiusUom === 'm')) {
250									// convert miles to kilometers
251									radius = (+radius * 1.609);
252								}
253
254								if (radius && (status === google.maps.GeocoderStatus.OK)) {
255									myOptions.circle = new google.maps.Circle({
256										center: results[0].geometry.location,
257										map: map[x],
258										radius: radius * 1000, // meters
259										clickable: false,
260										fillOpacity: 0.2,
261										fillColor: '#0056B7',
262										strokeWeight: 2,
263										strokeColor: '#0056B7',
264										zoomControl: false,
265									});
266									map[x].circleBounds = myOptions.circle.getBounds();
267									map[x].fitBounds(map[x].circleBounds);
268								}
269							});
270						}
271						
272						if (myOptions && myOptions.enableEvChargers) {
273							//Constraints for rendering the pins on the map
274							var evRadius = 0.1; 
275							var evMarkerCap = 250; 
276
277							var evData = getEvData();
278							if (evData && evData.length != 0) {
279								map[0].setOptions({ minZoom: 12 });	// minZoom level set to prevent performance issues, page breaks if too many markers rendered
280								var svgMarker = {
281									path: "M18.88 57.82C22.0267 58.2133 37.76 29.3071 37.76 18.88C37.76 8.45286 29.3071 0 18.88 0C8.45286 0 0 8.45286 0 18.88C0 29.3071 15.7333 57.4267 18.88 57.82ZM20.6762 19.6669H25.0253C25.2035 19.6668 25.378 19.7182 25.5282 19.815C25.6785 19.9119 25.7982 20.0501 25.8732 20.2134C25.9482 20.3768 25.9754 20.5584 25.9516 20.7368C25.9279 20.9153 25.854 21.0831 25.7389 21.2206L15.464 33.4913C15.3254 33.6572 15.1345 33.7699 14.9234 33.8102C14.7122 33.8506 14.4938 33.8161 14.3049 33.7127C14.116 33.6092 13.9681 33.4431 13.8862 33.2424C13.8044 33.0416 13.7935 32.8185 13.8555 32.6106L16.2972 24.3864H11.948C11.7698 24.3865 11.5953 24.3351 11.4451 24.2383C11.2949 24.1415 11.1752 24.0032 11.1002 23.8399C11.0251 23.6766 10.9979 23.495 11.0217 23.3165C11.0455 23.1381 11.1193 22.9702 11.2344 22.8328L21.5094 10.5621C21.6479 10.3961 21.8388 10.2834 22.0499 10.2431C22.2611 10.2028 22.4795 10.2372 22.6684 10.3407C22.8574 10.4441 23.0052 10.6102 23.0871 10.8109C23.169 11.0117 23.1798 11.2348 23.1179 11.4427L20.6762 19.6669Z",
282									fillColor: "#33D0F2",
283									fillOpacity: 0.9,
284									rotation: 0,
285									scale: 0.6,
286									anchor: new google.maps.Point(15, 30),
287								  };
288								
289								  google.maps.event.addListener(map[x], "initialize", function(){
290								})
291
292								pointList = []
293								var currentLat = currentCoords.center.lat(); 
294								var currentLng = currentCoords.center.lng();
295								
296								evData.forEach(function(el) {
297									var dx = Math.abs(currentLat - el[0]);
298									var dy = Math.abs(currentLng - el[1]);
299									if(dx <= evRadius && dy <= evRadius && pointList.length < evMarkerCap){
300										pointList.push( new google.maps.LatLng(el[0], el[1]))
301									}
302								});
303								
304								markers = []
305								pointList.forEach(function(el) {
306									markers.push(new google.maps.Marker({
307										position: el,
308										map: map[x],
309										icon: svgMarker,
310										optimized: true,
311										clickable: false,
312									}))
313								})
314								new markerClusterer.MarkerClusterer({ map: map[x], markers: markers });
315							};
316						};
317						
318						$(currentCoordList).each(function(i) {
319							var coord = currentCoordList[i],
320								windowMaxWidth = myOptions.data.markerInfoWindowMaxWidth != 'undefined' ? myOptions.data.markerInfoWindowMaxWidth : 1000,
321								enableInfoWindow = myOptions.enableInfoWindow != undefined,
322								markerLabel = $(myOptions.infoWindows[i]).data("marker-label"),
323								setOptimized = !($(myOptions.infoWindows[0]).is(".marker-labels"));
324
325							if (coord !== undefined && isLatLng(coord) && !coord.marker) {
326								coord.marker = new google.maps.Marker({
327									position: coord,
328									map: map[x],
329									infoClass: myOptions.infoWindows[i],
330									enableInfoWindow: enableInfoWindow,
331									optimized: setOptimized
332								});
333								
334								if(myOptions.customMarker) {
335									// %E2%80%A2 is the "dot" in the center of the marker.
336									var currentLabel = markerLabel != undefined ? markerLabel.toString() : "%E2%80%A2";
337									coord.marker.defaultMarker = myOptions.hasOwnProperty("markerImage") ? myOptions.markerImage : myOptions.hasOwnProperty("markerColor") ? getMarker(myOptions.markerColor.replace('#',''), myOptions.markerLabelColor.replace('#',''), currentLabel) : undefined;
338									coord.marker.selectedMarker = myOptions.hasOwnProperty("markerSelectedImage") && myOptions.hasOwnProperty("markerImage") ? myOptions.markerSelectedImage : myOptions.hasOwnProperty("markerSelectedColor") && myOptions.hasOwnProperty("markerColor") && !myOptions.hasOwnProperty("markerImage") ? getMarker(myOptions.markerSelectedColor.replace('#',''), myOptions.markerSelectedLabelColor.replace('#',''), currentLabel) : undefined;
339									coord.marker.setIcon(coord.marker.defaultMarker);
340
341									if(myOptions.hasOwnProperty("markerImage") && markerLabel != undefined){
342										coord.marker.setLabel(markerLabel.toString())
343									}
344								}else if(markerLabel != undefined){
345									coord.marker.setLabel(markerLabel.toString())
346								}
347
348								DDC.googleMapsMarkers[i] = coord;
349
350								if (myOptions.infoWindows && myOptions.infoWindows[i] && !coord.infoWindow) {
351									coord.infoWindow = new google.maps.InfoWindow({
352										content: '<div class="infowindow-wrap" style="min-height: 100px;">' + $(myOptions.infoWindows[i]).html() + '</div>',
353										maxWidth: windowMaxWidth
354									});
355
356									if ($.getDataAttributes(myOptions.infoWindows[i]).infoWindowEvent) {
357										$(myOptions.infoWindows[i]).bind($.getDataAttributes(myOptions.infoWindows[i]).infoWindowEvent, function() {
358											google.maps.event.trigger(coord.marker, 'click');
359											map[x].panTo(new google.maps.LatLng(coord.lat(),coord.lng()));
360										});
361									}
362									google.maps.event.addListener(coord.marker, 'click', function () {
363										// resetting previously selected marker back to default
364										if(DDC.modules.googleMap["previous"].hasOwnProperty("marker")){
365											DDC.modules.googleMap["previous"].marker.setIcon(DDC.modules.googleMap["previous"].marker.defaultMarker);
366											DDC.modules.googleMap["previous"].marker.setZIndex(google.maps.Marker.MAX_ZINDEX - 1);
367										}
368										if(DDC.modules.googleMap["previous"].hasOwnProperty("infoWindow")){
369											DDC.modules.googleMap["previous"].infoWindow.close();
370										}
371
372										// Setting current marker as previous marker (all maps have cord.marker)
373										DDC.modules.googleMap["previous"].marker = coord.marker;
374
375										if(coord.marker.selectedMarker != undefined) {
376											coord.marker.setIcon(coord.marker.selectedMarker);
377										}
378										// Moving current map marker to the top z-index
379										coord.marker.setZIndex(google.maps.Marker.MAX_ZINDEX + 1);
380
381										if(enableInfoWindow){
382											coord.infoWindow.open(coord.marker.map, coord.marker);
383											// Setting current infoWindow as previous infoWindow onlt ifinfo windows are enabled
384											DDC.modules.googleMap["previous"].infoWindow = coord.infoWindow;
385										}else {
386											// if the marker is outside the bounds of the map, this will center the map on the marker
387											var currentMapBounds = coord.marker.map.getBounds();
388											if (!currentMapBounds.contains(coord.marker.position)) {
389												coord.marker.map.panTo(coord.marker.position);
390											}
391										}
392
393										$(document).trigger('marker-clicked-google-maps', coord.marker);
394									});
395								}
396							}
397						});
398					}
399
400					if (map[x] && currentCoords.list.length > 1 && !ignoreBounds) {
401						map[x].fitBounds(currentCoords.getBounds());
402					}
403				},
404				toggleMarkers = function(showMarkers) {
405					// hard coding currentCoordList to use first object on directions pages
406					var coordList = mapCoordsList[0].getList();
407
408					$(coordList).each(function(i) {
409						coordList[i].marker.setVisible(showMarkers);
410
411						if (coordList[i].infoWindow) {
412							coordList[i].infoWindow.close();
413						}
414					});
415				},
416				getMarker = function(color, labelColor, label){
417					return "https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=" + label + "|" + color + "|" + labelColor;
418				};
419
420			$(DDC.modules.googleMap.selector).each(function() {
421				mapEl = $(this);
422				if (mapEl.attr('map-initialized') === 'true') {
423					return;
424				};
425				myOptions = $.getDataAttributes(this);
426				mapEl.attr('map-initialized', 'true');
427				markerAddresses = [],
428					myOptions.customMarker = myOptions.hasOwnProperty("markerColor") || myOptions.hasOwnProperty("markerImage"),
429					widgetClass = mapEl.closest('div[data-widget-id]').attr('data-widget-id'),
430					myOptions.infoWindows = [];
431
432				if ($.getDataAttributes(this).infoWindows) {
433					$.each( $.getDataAttributes(this).infoWindows.split(','), function(i, info) {
434						myOptions.infoWindows.push("[data-widget-id=" + widgetClass + "] " + info);
435					});
436				} else {
437					myOptions.infoWindows = null;
438				}
439
440				myOptions.data = $.getDataAttributes(this);
441				if (myOptions.data.mapGetMarkersByAddress && myOptions.data.mapGetMarkersByAddress === true) {
442					myOptions.data.markersList = myOptions.data.markersList.replace(/\'/g, '"');
443					myOptions.markersList = myOptions.markersList ? $.parseJSON(myOptions.data.markersList) : null;
444
445					for (var x = 0; x < myOptions.markersList.length; x++) {
446						markerAddresses.push($.makeArray(myOptions.markersList[x].storeLocation));
447					}
448
449					myOptions.markersList = markerAddresses;
450				} else {
451					myOptions.markersList = myOptions.markersList ? $.parseJSON(myOptions.markersList) : null;
452				}
453
454				myOptions.mapTypeId = myOptions.mapTypeId ? google.maps.MapTypeId[$.getDataAttributes(this).mapTypeId] : google.maps.MapTypeId.ROADMAP;
455
456				var mapCoords = new coords();
457				mapCoords.addCoords(myOptions.markersList, $(this), mapCoords, DDC.modules.googleMap.mapNumber++);
458			});
459
460			$(document)
461				.unbind('.google-maps')
462				// set up map refresh events
463				.bind('map-refresh.google-maps', function(ev, data) {
464					var map = DDC.googleMaps[data.mapCounter],
465						zoom = data.zoom ? data.zoom : map.getZoom();
466
467					google.maps.event.trigger(map, 'resize');
468
469					if (map.circleBounds) {
470						map.fitBounds(map.circleBounds);
471					} else{
472						map.setZoom(zoom);
473						map.setCenter(map.originalCenter);
474					}
475				})
476
477				// set up directions events
478				.bind('directions-search.google-maps', function(ev, data) {
479					if (data && data.directions.origin && data.directions.destination) {
480						$.extend(data.directions, {
481							travelMode: google.maps.DirectionsTravelMode.DRIVING
482						});
483						directionsService.route(data.directions, function(results, status) {
484							if (status === google.maps.DirectionsStatus.OK) {
485								$.extend(data, {results: results});
486								$(document).trigger('directions-results', data);
487							}
488						});
489					} else {
490						return data;
491					}
492				})
493				.bind('directions-results.google-maps', function(ev, data) {
494					toggleMarkers(hide);
495
496					if (data && data.results) {
497						$.each(DDC.googleMaps, function(i, map) {
498							if ($(map.getDiv()).is(':visible')) {
499								map.directionsRenderer = map.directionsRenderer || new google.maps.DirectionsRenderer();
500								map.directionsRenderer.setMap(map);
501								map.directionsRenderer.setDirections(data.results);
502							}
503
504							if ($('.directions-results').get(i) &&
505								map.directionsRenderer) {
506								map.directionsRenderer.setPanel($('.directions-results').get(i));
507							}
508						});
509					}
510				})
511				.bind('directions-reset.google-maps', function(ev) {
512					map.directionsRenderer.setMap(null);
513					toggleMarkers(show);
514					$('.directions-results').empty();
515				});
516
517
518			// trigger on full initialization with directions events
519			$(document).trigger('googleMapInitialized');
520		}
521	};
522}());

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.