1 /**
  2  * @fileOverview  
  3  * Copyright (c) 2013 Regione Autonoma della Sardegna
  4  * Published under the GPL license.<br>
  5  * See <a href="https://sardegnageoportale.it/webgis/license.txt">https://sardegnageoportale.it/webgis/license.txt</a>
  6  * for the full text of the license.
  7  * @version 0.1
  8  */
  9  
 10  /**
 11  * @require OpenLayers/Control/SelectFeature.js
 12  */
 13 
 14 Ext.namespace("framework.form");
 15 
 16 /**
 17  * Creates a textfield for coordinates search.
 18  * If coordinates are valid, the map will be centred on them and eventually zoomed.
 19  * @name_ CoordinateInputBox
 20  * @class Creates a combo box that handles results from a geocoding service OpenLS.
 21  * @constructor
 22  @extends <a target="_blank" href="http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.form.ComboBox">Ext.form.ComboBox</a>
 23  */
 24 framework.form.CoordinateInputBox = Ext.extend(Ext.form.TextField,
 25         /** 
 26          * @lends framework.form.CoordinateInputBox.prototype 
 27          */
 28                 {
 29                     /**
 30                      * Text to display for an empty field
 31                      * @public
 32                      * @type String
 33                      */
 34                     emptyText: "Coordinate to search for",
 35                     /**
 36                      * The srs used by the geocoder service.
 37                      * Default is "EPSG:4326".
 38                      * @public
 39                      * @type String
 40                      */
 41                     srs: "EPSG:4326",
 42                     /**
 43                      * The bounding box to validate coordinates.
 44                      * Outside this bounding box coordinates are considered invalid.
 45                      * Default is null to not perform validation
 46                      */
 47                     maxExtent: null,
 48                     /** 
 49                      * The minimum zoom level to use when zooming to a location.
 50                      * Not used when zooming to a bounding box. Default is 12.
 51                      * @public
 52                      * @type number
 53                      */
 54                     zoom: 12,
 55                     /** 
 56                      * If provided, a marker will be drawn on this
 57                      * layer with the location returned by the geocoder. The location will be
 58                      * cleared when the map panned. 
 59                      * @public
 60                      * @type OpenLayers.Layer.Vector
 61                      */
 62                     layer: null,
 63                     /** 
 64                      * style point result
 65                      * @public
 66                      * @type OpenLayers.Layer.Vector
 67                      */
 68                     vectorStyle: null,
 69                     /**
 70                      * See http://www.dev.sencha.com/deploy/dev/docs/source/BoxComponent.html#cfg-Ext.BoxComponent-width,
 71                      * default value is 240.
 72                      * @public
 73                      * @type Number
 74                      */
 75                     width: 240,
 76                     /**
 77                      * See http://www.dev.sencha.com/deploy/dev/docs/source/Combo.html#cfg-Ext.form.ComboBox-listWidth,
 78                      * default value is 350.
 79                      * @public
 80                      * @type Number
 81                      */
 82                     listWidth: 400,
 83                     /**
 84                      * See http://www.dev.sencha.com/deploy/dev/docs/source/Combo.html#cfg-Ext.form.ComboBox-loadingText,
 85                      * default value is "Search in Geozet...".
 86                      * @public
 87                      * @type String
 88                      */
 89                     loadingText: 'Searching...',
 90                     /**
 91                      * Hide trigger of the combo.
 92                      * @private
 93                      * @type boolean
 94                      */
 95                     hideTrigger: true,
 96                     /**
 97                      * Force selection.
 98                      * @private
 99                      * @type boolean
100                      */
101                     forceSelection: false,
102                     /** private: property[countryCode]
103                      * countryCode, default is IT.
104                      * @private
105                      * @type String
106                      */
107                     initComponent: function() {
108 
109                         var epsgOutput = this.srs.replace("EPSG:", "");
110 
111                         if (!this.map) {
112                             var mapPanel = this.findParentBy(function(cmp) {
113                                 return cmp instanceof GeoExt.MapPanel;
114                             });
115                             this.map = mapPanel.map;
116                         }
117                         if (Ext.isString(this.srs)) {
118                             this.srs = new OpenLayers.Projection(this.srs);
119                         }
120                         this.on({
121                             focus: function() {
122                                 this.clearResult();
123                             },
124                             scope: this
125                         });
126                         this.on({
127                             specialkey: function(f, e) {
128                                 if (e.getKey() === e.ENTER) {
129                                     this.doQuery(this.getValue(),true);
130                                 }
131                             }, scope: this
132                         });
133 
134                         if (this.layer) {
135 
136                             this.map.addLayer(this.layer);
137 
138                             this.selectCtrl = new OpenLayers.Control.SelectFeature([this.layer], {
139                                 toggle: true,
140                                 clickout: true
141                             });
142 
143                             this.map.addControl(this.selectCtrl);
144                             this.selectCtrl.activate();
145                         }
146 
147 
148                         return framework.form.GeocoderOpenLSComboBox.superclass.initComponent.apply(this, arguments);
149                     },
150                     /** 
151                      *  Handler for the map's moveend event. Clears the selected location
152                      *  when the map center has changed.
153                      *  @private
154                      */
155                     clearResult: function() {
156                         this.setValue("");
157                     },
158                     /** 
159                      *  Set the :obj:`map` for this instance.
160                      *  @private
161                      *  @param {GeoExt.MapPanel||OpenLayers.Map} map object
162                      */
163                     setMap: function(map) {
164                         if (map instanceof GeoExt.MapPanel) {
165                             map = map.map;
166                         }
167                         this.map = map;
168                         map.events.on({
169                             // "moveend": this.clearResult,
170                             //  "click": this.removeFocus,
171                             scope: this
172                         });
173                     },
174                     /** 
175                      *  Called by a MapPanel if this component is one of the items in the panel.
176                      *  @private
177                      */
178                     addToMapPanel: Ext.emptyFn,
179                     /** 
180                      * Zoom to the selected location, and also set a location marker if this
181                      * component was configured with an :obj:`layer`.
182                      * @private
183                      * @param {String} q query containing only the coordinates
184                      * @param {Boolean} forceAll not used for this component (but it's present
185                      * for compatibility issues).
186                      */
187                     doQuery: function(q, forceAll) {
188                         var data = q.split(",");
189                         if (data.length !== 2 || data[0] === undefined || data[1] === undefined) {
190                              Ext.MessageBox.alert('Errore', 'Coordinate non valide ' + q);
191                              return;
192                         }
193                         var lat = parseInt(data[1]);
194                         var lon = parseInt(data[0]);
195                         if (isNaN(lat)) {
196                             Ext.MessageBox.alert('Errore', 'Latitudine non valida ' + data[1]);
197                             return;
198                         }
199                         if (isNaN(lon)) {
200                             Ext.MessageBox.alert('Errore', 'Longitudine non valida ' + data[0]);
201                             return;
202                         }
203                         if (Ext.isDefined(this.maxExtent) && this.maxExtent!== null && !this.maxExtent.contains(lon, lat)) {
204                             Ext.MessageBox.alert('Errore', 'Coordinate fuori range');
205                             return;
206                         }
207                         var position = new OpenLayers.LonLat(lon, lat);
208 
209                         // Reproject (if required)
210                         position.transform(
211                                 new OpenLayers.Projection(this.srs.projCode),
212                                 this.map.getProjectionObject()
213                                 );
214 
215                         // zoom in on the location
216                         if (this.zoom !== undefined) {
217                             this.map.setCenter(position, this.zoom);
218                         }
219 
220                         //insert marker
221 
222                         if (this.layer) {
223                             //remove marker and popup
224                             this.layer.destroyFeatures();
225                             removePopup();
226 
227                             var feature = new OpenLayers.Feature.Vector(
228                                     new OpenLayers.Geometry.Point(position.lon, position.lat),
229                                     null,
230                                     this.vectorStyle);
231 
232                             feature.text = q;
233 
234                             this.layer.addFeatures(feature);
235 
236                             createPopup(feature);
237 
238                             this.map.searchName = this.id;
239 
240                             // create popup on "featureselected"
241                             this.layer.events.on({
242                                 featureselected: function(e) {
243                                     createPopup(e.feature);
244                                 }
245                             });
246                         }
247 
248                         function createPopup(feature) {
249                             removePopup();
250                             var feature_ = feature;
251                             this.popupAddr = new GeoExt.Popup({
252                                 //title: 'Ricerca indirizzo',
253                                 //map: this.map,
254                                 location: feature_,
255                                 width: 200,
256                                 border: false,
257                                 html: '<div class="popupAddr">' + feature_.text + '</div>',
258                                 maximizable: false,
259                                 collapsible: false
260                             });
261                             this.popupAddr.show();
262                         }
263 
264 
265                         function removePopup() {
266                             if (this.popupAddr) {
267                                 this.popupAddr.close();
268                                 this.popupAddr.destroy();
269                             }
270 
271                         }
272                     }
273 
274 
275                 });
276 
277         /** api: xtype = gx_geocoderopenlscombobox */
278         Ext.reg("framework_coordinateinputbox", framework.form.CoordinateInputBox);
279