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