1 (function($){
  2 	'use strict';		
  3 	
  4 	/**
  5 	* enable direction label (autocomplete etc.)
  6 	* @param {Object} self - this object
  7 	* @param {jQueryObject} $directionLabel - directions label
  8 	* @param {jQueryObject} $input - directions input field
  9 	* @param {number} latitude
 10 	* @param {number} longitude
 11 	*/
 12 	var enableDirectionLabel = function(self, $directionLabel, $input, latitude, longitude){
 13 		
 14 		var autocomplete
 15 			,listenerHandle;
 16 		
 17 		//add data attribute
 18 		$directionLabel.attr('data-enabled', 'true');
 19 		
 20 		if($input.length > 0){
 21 				
 22 			//init input autocomplete
 23 			autocomplete = new google.maps.places.Autocomplete($input.get(0));
 24 			autocomplete.jlocator = {
 25 				latitude: latitude
 26 				,longitude: longitude
 27 			};
 28 			
 29 			//autocomplete listener
 30 			listenerHandle = google.maps.event.addListener(autocomplete, 'place_changed', function(){
 31 		
 32 				var place
 33 					,start
 34 					,end
 35 					,jlocator;
 36 				
 37 				//get jlocator data
 38 				jlocator = this['jlocator'];
 39 				
 40 				//get choosen place
 41 				place = autocomplete.getPlace();					
 42 				
 43 				if(place && place.geometry){
 44 				
 45 					//get points
 46 					start = new google.maps.LatLng(jlocator['latitude'], jlocator['longitude']);
 47 					end = new google.maps.LatLng(place.geometry.location["lat"](), place.geometry.location["lng"]());
 48 					
 49 					//trigger set directions event
 50 					self.$root.trigger(self.options.setDirectionsEvent, [start, end]);					
 51 				}
 52 			});
 53 		}
 54 	};
 55 	
 56 	/**
 57 	* init directions events
 58 	* @param {Object} self - this object
 59 	* @param {jQueryObject} $directionLabel
 60 	*/
 61 	var initDirectionEvents = function(self, $directionLabel){
 62 		
 63 		var $dataItem
 64 			,latitude
 65 			,longitude
 66 			,$input
 67 			,isVisible
 68 			,enabled;
 69 		
 70 		//close all inputs
 71 		self.$panelRoot.find('[data-type="directions-input"]').hide(0);
 72 				
 73 		if($directionLabel.length > 0){
 74 			
 75 			//get vars
 76 			enabled = $directionLabel.attr('data-enabled');
 77 			$dataItem = $directionLabel.parents('[data-type="store"]');
 78 			$input = $dataItem.find('[data-type="directions-input"]');
 79 			
 80 			//if direcion label is not enabled -> enable it (autocomplete, its handler etc.)
 81 			if(!enabled && $dataItem.length > 0){
 82 				
 83 				//get vars
 84 				latitude = Number($dataItem.attr('data-latitude'));
 85 				longitude = Number($dataItem.attr('data-longitude'));
 86 				
 87 				if(!isNaN(latitude) && !isNaN(longitude)){					
 88 					enableDirectionLabel(self, $directionLabel, $input, latitude, longitude);
 89 				}
 90 			}
 91 			
 92 			if($input.length > 0){
 93 
 94 				isVisible = $input.is(':visible');
 95 				
 96 				if(isVisible){
 97 					$input.hide(0);
 98 				}
 99 				else{
100 					$input.show(0);
101 				}
102 			}
103 		}
104 	};
105 	
106 	/**
107 	* init events
108 	* @param {Object} self - 'this' object
109 	*/
110 	var initEvents = function(self){
111 		
112 		/**
113 		* store onclick
114 		*/
115 		self.$root.on('click', '[data-type="stores"] [data-type="store"]', function(){
116 			
117 			var store
118 				,$store;
119 			
120 			$store = $(this);
121 			
122 			//init store
123 			store = new jQuery.fn.jlocator.store($store, self.options);
124 			
125 			//trigger event
126 			self.$root.trigger(self.options.storeClickEvent, [store]);
127 			
128 			//remove active class from all current visible stores
129 			self.$panelRoot.find('[data-type="stores"] [data-type="store"]').removeClass('active');
130 			
131 			//add active class to the current store
132 			$store.addClass('active');
133 		});
134 		
135 		/**
136 		* get stores list event
137 		*/
138 		self.$root.on(self.options.getStoresListEvent, function(){
139 			
140 			//trigger send stores list event
141 			self.$root.trigger(self.options.sendStoreListEvent, [self.stores, getStoresView(self)]);
142 		});
143 		
144 		/**
145 		* init direction events
146 		*/
147 		self.$root.on('click', '[data-type="directions-label"]', function(){			
148 			initDirectionEvents(self, $(this));
149 		});
150 		
151 		/**
152 		* bind map pin click event
153 		*/
154 		self.$root.on(self.options.pinClickEvent, function(e, store){
155 			
156 			var longitude = store.longitude
157 				,latitude = store.latitude
158 				,$store
159 				,$stores;
160 				
161 			if($.isNumeric(longitude) && $.isNumeric(latitude)){
162 				
163 				//get all visible stores
164 				$stores = self.$panelRoot.find('[data-type="stores"] [data-type="store"]');
165 			
166 				//get store
167 				$store = $stores.filter('[data-longitude="' + longitude + '"][data-latitude="' + latitude + '"]');
168 				
169 				if($store.length > 0){
170 					
171 					$stores.removeClass('active');
172 					$store.addClass('active');
173 				}
174 			}
175 		});
176 	};
177 	
178 	/**
179 	* get stores view (current store list)
180 	* @param {Object} self - 'this' object
181 	* @return {Array.<jQuery.fn.jlocator.store>} - stores view (current store list)
182 	*/
183 	var getStoresView = function(self){
184 		
185 		var store
186 			,storesView = [];
187 		
188 		self.$panelRoot.find('[data-type="stores"] [data-type="store"]').each(function(){
189 						
190 			//init store
191 			store = new jQuery.fn.jlocator.store($(this), self.options);
192 			
193 			storesView.push(store);
194 		});
195 		
196 		return storesView;
197 	};
198 	
199 	/**
200 	* init full stores list
201 	* @param {Object} self - 'this' object
202 	* @return {Array.<jQuery.fn.jlocator.store>} - full stores list
203 	*/
204 	var initStoresList = function(self){
205 		
206 		var store
207 			,stores = [];
208 		
209 		self.$stores.each(function(){
210 						
211 			//init store
212 			store = new jQuery.fn.jlocator.store($(this), self.options);
213 			
214 			stores.push(store);
215 		});
216 		
217 		return stores;
218 	};
219 	
220 	/**
221 	* init jplist plugin: http://jplist.no81no.com/
222 	* @param {Object} self - 'this' object
223 	* @param {jQueryObject} $root - jlocator root element
224 	*/
225 	var initJPlist = function(self, $root){
226 		
227 		var saveCallback = self.options.jplist.redraw_callback;
228 		
229 		if($root.length > 0){
230 		
231 			self.options.jplist.redraw_callback = function(){
232 				
233 				if($.isFunction(saveCallback)){
234 					saveCallback();
235 					
236 					//trigger send stores list event
237 					self.$root.trigger(self.options.sendStoreListEvent, [self.stores, getStoresView(self)]);
238 				}
239 			};
240 			
241 			$root.jplist(self.options.jplist);
242 		}
243 	};
244 	
245 	/**
246 	* panel constructor
247 	* @param {jQueryObject} $root - jlocator root element
248 	* @param {Object} options - jlocator user options
249 	* @return {Object} - panel + this	
250 	* @constructor 
251 	*/
252 	var Init = function($root, options){
253 	
254 		var self = {
255 			$root: $root
256 			,options: options
257 			,stores: []
258 			
259 			//elements
260 			,$panelRoot: $root.find('[data-type="panel"]')
261 			,$stores: null
262 		};	
263 
264 		//init vars
265 		self.$stores = self.$panelRoot.find('[data-type="stores"] [data-type="store"]');
266 		
267 		//init store list
268 		self.stores = initStoresList(self);
269 		
270 		//init jplist plugin
271 		initJPlist(self, self.$root);
272 				
273 		return $.extend(this, self);
274 	};
275 	
276 	/**
277 	* panel constructor
278 	* @param {jQueryObject} $root - jlocator root element
279 	* @param {Object} options - jlocator user options
280 	* @return {Object} - panel
281 	* @constructor 
282 	* @name panel
283     * @class Controller
284     * @memberOf jQuery.fn.jlocator
285 	* @property {jQueryObject} $root - jlocator root element
286 	* @property {Object} options - jlocator user options
287 	* @property {Array.<jQuery.fn.jlocator.store>} stores - jlocator stores array
288 	* @property {jQueryObject} $panelRoot - panel root element
289 	* @property {jQueryObject} $stores - stores list as jquery element
290 	*/
291 	jQuery.fn.jlocator.panel = function($root, options){
292 				
293 		//call constructor
294 		var self = new Init($root, options);	
295 
296 		//init events
297 		initEvents(self);
298 		
299 		return self;
300 	};
301 })(jQuery);
302 
303