1 (function($){
  2 	'use strict';		
  3 	
  4 	/**
  5 	* set directions
  6 	* @param {Object} self - this object
  7 	* @param {Object|string} start
  8 	* @param {Object|string} end
  9 	*/
 10 	var setDirections = function(self, start, end){
 11 	
 12 		var request;
 13 		
 14 		//init request
 15 		request = {
 16             origin:start
 17             ,destination:end
 18             ,travelMode: google.maps['DirectionsTravelMode'][self.options.directionsType]
 19         };
 20 		
 21 		self.directionsService['route'](request, function(response, status){
 22 			
 23 			if(status == google.maps['DirectionsStatus']['OK']){
 24 				self.directionsDisplay['setDirections'](response);
 25 			}
 26         });
 27 	};
 28 	
 29 	/**
 30 	* close all info windows
 31 	* @param {Object} self - this object
 32 	*/
 33 	var closeAllInfoWindows = function(self){
 34 	
 35 		var cmarker;
 36 		
 37 		//close all opened info windows
 38 		for(var i=0; i<self.markers.length; i++){
 39 		
 40 			//marker
 41 			cmarker = self.markers[i];
 42 			
 43 			if(cmarker.infowindow){
 44 				cmarker.infowindow.close();
 45 			}
 46 		}
 47 	};
 48 	
 49 	/**
 50 	* open info window
 51 	* @param {Object} self - this object
 52 	* @param {Object} marker
 53 	*/
 54 	var openInfoWindow = function(self, marker){
 55 	
 56 		//close all info windows
 57 		closeAllInfoWindows(self);
 58 		
 59 		//open current info window
 60 		marker.infowindow.open(self.mapCanvas, marker);
 61 	};
 62 	
 63 	/**
 64 	* clear markers
 65 	* @param {Object} self - this object
 66 	*/
 67 	var clearMarkers = function(self){
 68 		
 69 		var marker;
 70 		
 71 		for(var i=0; i<self.markers.length; i++){
 72 		
 73 			//get marker
 74 			marker = self.markers[i];
 75 			
 76 			//clear marker
 77 			marker.setMap(null);
 78 		}
 79 		
 80 		//empty markers
 81 		self.markers = [];
 82 	};
 83 	
 84 	/**
 85 	* find marker by store
 86 	* @param {Object} self - this object
 87 	* @param {jQuery.fn.jlocator.store} store
 88 	* @return {Object|null} marker
 89 	*/
 90 	var findMarker = function(self, store){
 91 		
 92 		var marker
 93 			,markerStore;
 94 		
 95 		for(var i=0; i<self.markers.length; i++){
 96 			
 97 			//get marker
 98 			marker = self.markers[i];
 99 			
100 			//get marker store
101 			markerStore = marker['store'];
102 			
103 			if(markerStore && 
104 				markerStore.latitude === store.latitude &&
105 				markerStore.longitude === store.longitude){
106 				
107 				return marker;
108 			}
109 		}
110 		
111 		return null;
112 	};
113 	
114 	/**
115 	* set markers
116 	* @param {Object} self - this object
117 	* @param {jQuery.fn.jlocator.store} store
118 	*/
119 	var setMarker = function(self, store){
120 		
121 		var infowindow
122 			,marker
123 			,markerSettings;
124 		
125 		//init info window
126 		infowindow = new google.maps.InfoWindow();
127 		
128 		//set info window html
129 		if($.isFunction(self.options.infoWindow)){
130 			infowindow.setContent(self.options.infoWindow(store['html'], store.title, store.address, store.city, store.state, store.zipcode, store.country));
131 		}
132 		
133 		//init marker settings
134 		markerSettings = {
135 			position: store.latlng
136 			,map: self.mapCanvas
137 			,title: self.options.markerText
138 		};
139 		
140 		//marker icon
141 		if(store.customMarkerIcon !== ''){
142 			markerSettings.icon = store.customMarkerIcon;
143 		}
144 		else{
145 			if(self.options.markerIcon !== ''){
146 				markerSettings.icon = self.options.markerIcon;
147 			}
148 		}
149 		
150 		//create marker
151 		marker = new google.maps.Marker(markerSettings);
152 		
153 		$.extend(marker,{
154 			infowindow: infowindow
155 			,store: store
156 		});	
157 		
158 		//add marker to the markers list
159 		self.markers.push(marker);
160 		
161 		google.maps.event.addListener(marker, 'click', function(e){			
162 			
163 			//open popup
164 			openInfoWindow(self, this);
165 			
166 			//trigger event
167 			self.$root.trigger(self.options.pinClickEvent, [store]);
168 		});
169 	};
170 	
171 	/**
172 	* set markers
173 	* @param {Object} self - this object
174 	* @param {Array.<jQuery.fn.jlocator.store>} stores
175 	*/
176 	var setMarkers = function(self, stores){	
177 		
178 		var store;
179 		
180 		//clear markers
181 		clearMarkers(self);
182 		
183 		for(var i=0; i<stores.length; i++){
184 		
185 			//get store
186 			store = stores[i];
187 			
188 			//set marker
189 			setMarker(self, store);
190 		}
191 	};
192 	
193 	/**
194 	* set zoom
195 	* @param {Object} self - this object
196 	* @param {number} zoom
197 	*/
198 	var setZoom = function(self, zoom){	
199 		self.mapCanvas.setZoom(zoom);
200 	};
201 	
202 	/**
203 	* jump
204 	* @param {Object} self - this object
205 	* @param {google.maps.LatLng} latlng
206 	* @param {number} zoom
207 	*/
208 	var jump = function(self, latlng, zoom){	
209 		self.mapCanvas.setCenter(latlng);
210 		self.mapCanvas.setZoom(zoom);
211 	};
212 	
213 	/**
214 	* init geolocation
215 	* @param {Object} self - this object
216 	*/	
217 	var initGeolocation = function(self){
218 	
219 		var latitude
220 			,longitude
221 			,latlng;
222 		
223 		if(self.options.geolocation && navigator.geolocation){
224 		
225 			navigator.geolocation.getCurrentPosition(function(position){
226 				
227 				latitude = position.coords.latitude;
228 				longitude = position.coords.longitude;	
229 				latlng = new google.maps.LatLng(latitude, longitude);
230 				
231 				//jump to map
232 				jump(self, latlng, self.options.storeZoom);	
233 			});
234 		}
235 	};
236 	
237 	/**
238 	* init events
239 	* @param {Object} self - 'this' object
240 	*/
241 	var initEvents = function(self){
242 		
243 		/**
244 		* on jump event
245 		*/
246 		self.$root.on(self.options.jumpEvent, function(e, latitude, longitude, zoom){
247 		
248 			var latlng = new google.maps.LatLng(latitude, longitude);
249 			
250 			jump(self, latlng, zoom);
251 		});
252 		
253 		/**
254 		* on init zoom event
255 		*/
256 		self.$root.on(self.options.initZoomEvent, function(e, zoom){		
257 			setZoom(self, zoom);
258 		});
259 		
260 		/**
261 		* bind store click event
262 		*/
263 		self.$root.on(self.options.storeClickEvent, function(e, store){
264 			
265 			var marker;
266 			
267 			if(store){
268 			
269 				//close all info windows
270 				closeAllInfoWindows(self);
271 								
272 				//jump to the store
273 				jump(self, store.latlng, store.zoom);
274 				
275 				if(self.options.openInfoWindowOnStoreClick){
276 					
277 					//get marker by store
278 					marker = findMarker(self, store);
279 										
280 					if(marker){
281 						google.maps.event.trigger(marker, 'click');
282 					}
283 				}
284 			}
285 		});
286 		
287 		/**
288 		* bind stores list event
289 		*/
290 		self.$root.on(self.options.sendStoreListEvent, function(e, fullStoresList, storesView){
291 			
292 			setMarkers(self, storesView);
293 		});
294 		
295 		/**
296 		* bind set directions event
297 		*/
298 		self.$root.on(self.options.setDirectionsEvent, function(e, start, end){			
299 			setDirections(self, start, end);			
300 		});
301 	};
302 	
303 	/**
304 	* init map
305 	* @param {Object} self - 'this' object
306 	* @param {jQueryObject} $mapRoot - map root jquery element
307 	*/
308 	var initMap = function(self, $mapRoot){
309 		
310 		var pyrmont;
311 				
312 		if(google && google.maps){
313 		
314 			google.maps.event.addDomListener(window, 'load', function(){
315 				
316 				//directions
317 				self.directionsService = new google.maps['DirectionsService']();
318 				self.directionsDisplay = new google.maps['DirectionsRenderer']();	
319 		
320 				//init pyrmont
321 				pyrmont = new google.maps.LatLng(self.options.latitude, self.options.longitude);
322 				
323 				//create map
324 				self.mapCanvas = new google.maps.Map(self.$mapRoot.get(0), 
325 				{
326 					mapTypeId: google.maps.MapTypeId[self.options.mapTypeId]
327 					,center: pyrmont
328 					,zoom: self.options.startZoom
329 				});
330 				
331 				//init directions display
332 				self.directionsDisplay.setMap(self.mapCanvas);
333 				
334 				//init events
335 				initEvents(self);
336 				
337 				//get stores list -> draw markers
338 				self.$root.trigger(self.options.getStoresListEvent, []);
339 				
340 				//init geolocation (if needed)
341 				initGeolocation(self);
342 			});
343 		}
344 	};
345 	
346 	/**
347 	* map constructor
348 	* @param {jQueryObject} $root - jlocator root element
349 	* @param {Object} options - jlocator user options
350 	* @return {Object} - map + this	
351 	* @constructor 
352 	*/
353 	var Init = function($root, options){
354 	
355 		var self = {
356 			$root: $root
357 			,options: options
358 			
359 			//map
360 			,mapCanvas: null
361 			,geocoder: null
362 			,markers: []
363 			
364 			//jplist
365 			,$mapRoot: $root.find('[data-type="map"]')
366 			
367 			//directions
368 			,directionsService: null
369 			,directionsDisplay: null
370 		};		
371 		
372 		//init map
373 		initMap(self, self.$mapRoot);
374 				
375 		return $.extend(this, self);
376 	};
377 	
378 	/**
379 	* map
380 	* @param {jQueryObject} $root - jlocator root element
381 	* @param {Object} options - jlocator user options
382 	* @return {Object} - map
383 	* @constructor 
384 	* @name map
385     * @class Controller
386     * @memberOf jQuery.fn.jlocator
387 	* @property {jQueryObject} $root - jlocator root element
388 	* @property {Object} options - jlocator user options
389 	* @property {Object} mapCanvas - map convas element
390 	* @property {Object} geocoder - google geocoder element
391 	* @property {jQueryObject} $mapRoot - map root element
392 	* @property {Object} directionsService - google directions service
393 	* @property {Object} directionsDisplay - google directions display
394 	*/
395 	jQuery.fn.jlocator.map = function($root, options){
396 				
397 		//call constructor
398 		return new Init($root, options);	
399 	};
400 })(jQuery);
401 
402