420ac01631e0fcd39a181172aef7c2a2a797c104
[roojs1] / Roo / bootstrap / LocationPicker.js
1 /*
2  * - LGPL
3  *
4  * Location Picker
5  * 
6  */
7
8 /**
9  * @class Roo.bootstrap.LocationPicker
10  * @extends Roo.bootstrap.Component
11  * Bootstrap LocationPicker class
12  * @cfg {Number} latitude Position when init default 0
13  * @cfg {Number} longitude Position when init default 0
14  * @cfg {Number} zoom default 15
15  * @cfg {String} mapTypeId default google.maps.MapTypeId.ROADMAP
16  * @cfg {Boolean} mapTypeControl default false
17  * @cfg {Boolean} disableDoubleClickZoom default false
18  * @cfg {Boolean} scrollwheel default true
19  * @cfg {Boolean} streetViewControl default false
20  * @cfg {Number} radius default 0
21  * @cfg {String} locationName
22  * @cfg {Boolean} draggable default true
23  * @cfg {Boolean} enableAutocomplete default false
24  * @cfg {Boolean} enableReverseGeocode default true
25  * @cfg {String} markerTitle
26  * 
27  * @constructor
28  * Create a new LocationPicker
29  * @param {Object} config The config object
30  */
31
32
33 Roo.bootstrap.LocationPicker = function(config){
34     
35     Roo.bootstrap.LocationPicker.superclass.constructor.call(this, config);
36     
37     this.addEvents({
38         /**
39          * @event initial
40          * Fires when the picker initialized.
41          * @param {Roo.bootstrap.LocationPicker} this
42          * @param {Google Location} location
43          */
44         initial : true,
45         /**
46          * @event positionchanged
47          * Fires when the picker position changed.
48          * @param {Roo.bootstrap.LocationPicker} this
49          * @param {Google Location} location
50          */
51         positionchanged : true,
52         /**
53          * @event resize
54          * Fires when the map resize.
55          * @param {Roo.bootstrap.LocationPicker} this
56          */
57         resize : true,
58         /**
59          * @event show
60          * Fires when the map show.
61          * @param {Roo.bootstrap.LocationPicker} this
62          */
63         show : true,
64         /**
65          * @event hide
66          * Fires when the map hide.
67          * @param {Roo.bootstrap.LocationPicker} this
68          */
69         hide : true,
70         /**
71          * @event mapClick
72          * Fires when click the map.
73          * @param {Roo.bootstrap.LocationPicker} this
74          * @param {Map event} e
75          */
76         mapClick : true,
77         /**
78          * @event mapRightClick
79          * Fires when right click the map.
80          * @param {Roo.bootstrap.LocationPicker} this
81          * @param {Map event} e
82          */
83         mapRightClick : true,
84         /**
85          * @event markerClick
86          * Fires when click the marker.
87          * @param {Roo.bootstrap.LocationPicker} this
88          * @param {Map event} e
89          */
90         markerClick : true,
91         /**
92          * @event markerRightClick
93          * Fires when right click the marker.
94          * @param {Roo.bootstrap.LocationPicker} this
95          * @param {Map event} e
96          */
97         markerRightClick : true,
98         /**
99          * @event OverlayViewDraw
100          * Fires when OverlayView Draw
101          * @param {Roo.bootstrap.LocationPicker} this
102          */
103         OverlayViewDraw : true,
104         /**
105          * @event OverlayViewOnAdd
106          * Fires when OverlayView Draw
107          * @param {Roo.bootstrap.LocationPicker} this
108          */
109         OverlayViewOnAdd : true,
110         /**
111          * @event OverlayViewOnRemove
112          * Fires when OverlayView Draw
113          * @param {Roo.bootstrap.LocationPicker} this
114          */
115         OverlayViewOnRemove : true,
116         /**
117          * @event OverlayViewShow
118          * Fires when OverlayView Draw
119          * @param {Roo.bootstrap.LocationPicker} this
120          * @param {Pixel} cpx
121          */
122         OverlayViewShow : true,
123         /**
124          * @event OverlayViewHide
125          * Fires when OverlayView Draw
126          * @param {Roo.bootstrap.LocationPicker} this
127          */
128         OverlayViewHide : true,
129         /**
130          * @event loadexception
131          * Fires when load google lib failed.
132          * @param {Roo.bootstrap.LocationPicker} this
133          */
134         loadexception : true
135     });
136         
137 };
138
139 Roo.extend(Roo.bootstrap.LocationPicker, Roo.bootstrap.Component,  {
140     
141     gMapContext: false,
142     
143     latitude: 0,
144     longitude: 0,
145     zoom: 15,
146     mapTypeId: false,
147     mapTypeControl: false,
148     disableDoubleClickZoom: false,
149     scrollwheel: true,
150     streetViewControl: false,
151     radius: 0,
152     locationName: '',
153     draggable: true,
154     enableAutocomplete: false,
155     enableReverseGeocode: true,
156     markerTitle: '',
157     
158     getAutoCreate: function()
159     {
160
161         var cfg = {
162             tag: 'div',
163             cls: 'roo-location-picker'
164         };
165         
166         return cfg
167     },
168     
169     initEvents: function(ct, position)
170     {       
171         Roo.log('initEvent');
172         if(!this.el.getWidth() || this.isApplied()){
173             return;
174         }
175         
176         Roo.log('start init');
177         this.el.setVisibilityMode(Roo.Element.DISPLAY);
178         
179         this.initial();
180     },
181     
182     initial: function()
183     {
184         if(typeof(google) == 'undefined' || typeof(google.maps) == 'undefined'){
185             this.fireEvent('loadexception', this);
186             return;
187         }
188         
189         if(!this.mapTypeId){
190             this.mapTypeId = google.maps.MapTypeId.ROADMAP;
191         }
192         
193         this.gMapContext = this.GMapContext();
194         
195         this.initOverlayView();
196         
197         this.OverlayView = new Roo.bootstrap.LocationPicker.OverlayView(this.gMapContext.map);
198         
199         var _this = this;
200                 
201         google.maps.event.addListener(this.gMapContext.marker, "dragend", function(event) {
202             _this.setPosition(_this.gMapContext.marker.position);
203         });
204         
205         google.maps.event.addListener(this.gMapContext.map, 'click', function(event){
206             _this.fireEvent('mapClick', this, event);
207             
208         });
209
210         google.maps.event.addListener(this.gMapContext.map, 'rightclick', function(event){
211             _this.fireEvent('mapRightClick', this, event);
212             
213         });
214         
215         google.maps.event.addListener(this.gMapContext.marker, 'click', function(event){
216             _this.fireEvent('markerClick', this, event);
217             
218         });
219
220         google.maps.event.addListener(this.gMapContext.marker, 'rightclick', function(event){
221             _this.fireEvent('markerRightClick', this, event);
222             
223         });
224         
225         this.setPosition(this.gMapContext.location);
226         
227         this.fireEvent('initial', this, this.gMapContext.location);
228     },
229     
230     initOverlayView: function()
231     {
232         var _this = this;
233         
234         Roo.bootstrap.LocationPicker.OverlayView.prototype = Roo.apply(new google.maps.OverlayView(), {
235             
236             draw: function()
237             {
238                 _this.fireEvent('OverlayViewDraw', _this);
239             },
240             
241             onAdd: function()
242             {
243                 _this.fireEvent('OverlayViewOnAdd', _this);
244             },
245             
246             onRemove: function()
247             {
248                 _this.fireEvent('OverlayViewOnRemove', _this);
249             },
250             
251             show: function(cpx)
252             {
253                 _this.fireEvent('OverlayViewShow', _this, cpx);
254             },
255             
256             hide: function()
257             {
258                 _this.fireEvent('OverlayViewHide', _this);
259             }
260             
261         });
262     },
263     
264     fromLatLngToContainerPixel: function(event)
265     {
266         return this.OverlayView.getProjection().fromLatLngToContainerPixel(event.latLng);
267     },
268     
269     isApplied: function() 
270     {
271         return this.getGmapContext() == false ? false : true;
272     },
273     
274     getGmapContext: function() 
275     {
276         return (typeof(this.gMapContext) == 'undefined') ? false : this.gMapContext;
277     },
278     
279     GMapContext: function() 
280     {
281         var position = new google.maps.LatLng(this.latitude, this.longitude);
282         
283         var _map = new google.maps.Map(this.el.dom, {
284             center: position,
285             zoom: this.zoom,
286             mapTypeId: this.mapTypeId,
287             mapTypeControl: this.mapTypeControl,
288             disableDoubleClickZoom: this.disableDoubleClickZoom,
289             scrollwheel: this.scrollwheel,
290             streetViewControl: this.streetViewControl,
291             locationName: this.locationName,
292             draggable: this.draggable,
293             enableAutocomplete: this.enableAutocomplete,
294             enableReverseGeocode: this.enableReverseGeocode
295         });
296         
297         var _marker = new google.maps.Marker({
298             position: position,
299             map: _map,
300             title: this.markerTitle,
301             draggable: this.draggable
302         });
303         
304         return {
305             map: _map,
306             marker: _marker,
307             circle: null,
308             location: position,
309             radius: this.radius,
310             locationName: this.locationName,
311             addressComponents: {
312                 formatted_address: null,
313                 addressLine1: null,
314                 addressLine2: null,
315                 streetName: null,
316                 streetNumber: null,
317                 city: null,
318                 district: null,
319                 state: null,
320                 stateOrProvince: null
321             },
322             settings: this,
323             domContainer: this.el.dom,
324             geodecoder: new google.maps.Geocoder()
325         };
326     },
327     
328     drawCircle: function(center, radius, options) 
329     {
330         if (this.gMapContext.circle != null) {
331             this.gMapContext.circle.setMap(null);
332         }
333         if (radius > 0) {
334             radius *= 1;
335             options = Roo.apply({}, options, {
336                 strokeColor: "#0000FF",
337                 strokeOpacity: .35,
338                 strokeWeight: 2,
339                 fillColor: "#0000FF",
340                 fillOpacity: .2
341             });
342             
343             options.map = this.gMapContext.map;
344             options.radius = radius;
345             options.center = center;
346             this.gMapContext.circle = new google.maps.Circle(options);
347             return this.gMapContext.circle;
348         }
349         
350         return null;
351     },
352     
353     setPosition: function(location) 
354     {
355         this.gMapContext.location = location;
356         this.gMapContext.marker.setPosition(location);
357         this.gMapContext.map.panTo(location);
358         this.drawCircle(location, this.gMapContext.radius, {});
359         
360         var _this = this;
361         
362         if (this.gMapContext.settings.enableReverseGeocode) {
363             this.gMapContext.geodecoder.geocode({
364                 latLng: this.gMapContext.location
365             }, function(results, status) {
366                 
367                 if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
368                     _this.gMapContext.locationName = results[0].formatted_address;
369                     _this.gMapContext.addressComponents = _this.address_component_from_google_geocode(results[0].address_components);
370                     
371                     _this.fireEvent('positionchanged', this, location);
372                 }
373             });
374             
375             return;
376         }
377         
378         this.fireEvent('positionchanged', this, location);
379     },
380     
381     resize: function()
382     {
383         google.maps.event.trigger(this.gMapContext.map, "resize");
384         
385         this.gMapContext.map.setCenter(this.gMapContext.marker.position);
386         
387         this.fireEvent('resize', this);
388     },
389     
390     setPositionByLatLng: function(latitude, longitude)
391     {
392         this.setPosition(new google.maps.LatLng(latitude, longitude));
393     },
394     
395     getCurrentPosition: function() 
396     {
397         return {
398             latitude: this.gMapContext.location.lat(),
399             longitude: this.gMapContext.location.lng()
400         };
401     },
402     
403     getAddressName: function() 
404     {
405         return this.gMapContext.locationName;
406     },
407     
408     getAddressComponents: function() 
409     {
410         return this.gMapContext.addressComponents;
411     },
412     
413     address_component_from_google_geocode: function(address_components) 
414     {
415         var result = {};
416         
417         for (var i = 0; i < address_components.length; i++) {
418             var component = address_components[i];
419             if (component.types.indexOf("postal_code") >= 0) {
420                 result.postalCode = component.short_name;
421             } else if (component.types.indexOf("street_number") >= 0) {
422                 result.streetNumber = component.short_name;
423             } else if (component.types.indexOf("route") >= 0) {
424                 result.streetName = component.short_name;
425             } else if (component.types.indexOf("neighborhood") >= 0) {
426                 result.city = component.short_name;
427             } else if (component.types.indexOf("locality") >= 0) {
428                 result.city = component.short_name;
429             } else if (component.types.indexOf("sublocality") >= 0) {
430                 result.district = component.short_name;
431             } else if (component.types.indexOf("administrative_area_level_1") >= 0) {
432                 result.stateOrProvince = component.short_name;
433             } else if (component.types.indexOf("country") >= 0) {
434                 result.country = component.short_name;
435             }
436         }
437         
438         result.addressLine1 = [ result.streetNumber, result.streetName ].join(" ").trim();
439         result.addressLine2 = "";
440         return result;
441     },
442     
443     setZoomLevel: function(zoom)
444     {
445         this.gMapContext.map.setZoom(zoom);
446     },
447     
448     show: function()
449     {
450         if(!this.el){
451             return;
452         }
453         
454         this.el.show();
455         
456         this.resize();
457         
458         this.fireEvent('show', this);
459     },
460     
461     hide: function()
462     {
463         if(!this.el){
464             return;
465         }
466         
467         this.el.hide();
468         
469         this.fireEvent('hide', this);
470     }
471     
472 });
473
474 Roo.apply(Roo.bootstrap.LocationPicker, {
475     
476     OverlayView : function(map, options)
477     {
478         options = options || {};
479         
480         this.setMap(map);
481     }
482     
483     
484 });