/*
* Copyright (c) 2013 Bundesamt by Kartographie und Geodäsie.
* See license.txt in the BKG WebMap distribution or repository for the
* full text of the license.
*
* Author: Dirk Thalheim
*/
/**
* @requires OpenLayers/BaseTypes/Class.js
* @requires OpenLayers/BaseTypes/Element.js
* @requires BKGWebMap/Util.js
* @requires BKGWebMap/Control/Search.js
* @requires BKGWebMap/Protocol/Geoindex.js
* @requires BKGWebMap/Util/AutoSuggest.js
*/
/**
*
* Zusätzliche Events:
* <ul>
* <li>error - Bei Fehlern in Geocodierung; zusätzliche Event-Property response</li>
* <li>locationupdate - Nach erfolgreicher Geocodierung; zusätzliche Event-Property response</li>
* <li>hoverfeature - Hervorheben eines Features</li>
* </ul>
* @classdesc Kontrollelement für Geocodierung
*
* @constructor BKGWebMap.Control.Geocoder
* @param {object} options - Optionen für das Controlelement
**/
BKGWebMap.Control.Geocoder = OpenLayers.Class(BKGWebMap.Control.Search, {
/**
* Protokoll für Interaktion mit Geocodierungsdienst
* @memberOf BKGWebMap.Control.Geocoder
* @type BKGWebMap.Protocol.Geoindex
*/
protocol: null,
/**
* Speichert die aktuelle Anfrage.
* @memberOf BKGWebMap.Control.Geocoder
* @type BKGWebMap.Protocol.Geoindex.Response
*/
response: null,
/**
* Beschränkung der Suche auf aktuellen Kartenausschnitt.
* @memberOf BKGWebMap.Control.Geocoder
* @type boolean
*/
useMapExtend: false,
/**
* Liste an Views für die Ergebnisdarstellung.
* @memberOf BKGWebMap.Control.Geocoder
* @type Array
*/
views: [],
labels: {
inputHint : 'Ortssuche',
search: 'Ortssuche'
},
initialize: function(options) {
options = options || {};
BKGWebMap.Control.Search.prototype.initialize.apply(this, [options]);
if(!this.protocol)
console.log("Kein Protokoll für den Geocoder gesetzt!");
BKGWebMap.Util.each(
this.views,
OpenLayers.Function.bind( function(index, view) { this.registerViewEvents(view); }, this )
);
},
setMap: function(map) {
BKGWebMap.Control.Search.prototype.setMap.apply(this, arguments);
// Projektion für Ortssuche setzen
this.protocol.srs = map.projection;
// ggf. extent setzen
var bounds = map.getMaxExtent();
if(map.projection in BKGWebMap.EXTENTS) {
var defaultBounds = BKGWebMap.EXTENTS[map.projection];
if (defaultBounds[0] < bounds.left || defaultBounds[1] < bounds.bottom ||
defaultBounds[2] > bounds.right || defaultBounds[3] > bounds.top) {
this.protocol.bounds = map.getMaxExtent();
}
}
// map den Views übergeben
BKGWebMap.Util.each( this.views, OpenLayers.Function.bind(function(index, view) { view.setMap(this); }, map) );
// Über Änderungen des Viewports informiert werden:
this.updateViewPort();
map.events.on({
moveend: this.updateViewPort,
scope: this
});
},
draw: function(px) {
var div = BKGWebMap.Control.Search.prototype.draw.apply(this);
// Autocomplete-Funktionalität initialisieren
if(this.protocol.canAutocomplete) {
this.autocomplete = new BKGWebMap.Util.AutoSuggest(this.input, this.protocol, {events: this.inputEvents});
}
return div;
},
/**
* Fügt eine View für die Ergebnisdarstellung dem Geocoder hinzu.
* @memberOf BKGWebMap.Control.Geocoder
* @param {BKGWebMap.Control.Geocoder.View} view - Die View für die ergebnisanzeige
*/
addView: function(view) {
this.views.push(view);
this.registerViewEvents(view);
if(this.map) view.setMap(this.map);
},
registerViewEvents: function(view) {
view.setGeocoder(this);
this.events.on({
"startsearch": view.onStartSearch,
"error": view.onError,
"locationupdate": view.onLocationUpdate,
"hoverfeature": view.onHoverFeature,
scope: view
});
},
/**
* Startet die Geocodierung
*
* @memberOf BKGWebMap.Control.Geocoder
*/
triggerSearch: function() {
BKGWebMap.Control.Search.prototype.triggerSearch.apply(this);
if(this.response) {
this.protocol.abort(this.response);
this.response = null;
}
OpenLayers.Element.addClass(this.searchButton, "active");
// stoppe AutoSuggest
if(this.autocomplete) {
this.autocomplete.hideSuggestions(); // hide the suggestion when searching
this.autocomplete.cancel();
}
this.response = this.protocol.geocode(this.getValue(), {callback: this.handleResult, scope: this});
},
/**
* Verarbeitet die Antwort vom Geocodierungsdienst
* @memberOf BKGWebMap.Control.Geocoder
* @param {BKGWebMap.Protocol.Geoindex.Response} response
*/
handleResult: function(response) {
OpenLayers.Element.removeClass(this.searchButton, "active");
this.response = null;
if(response.code != OpenLayers.Protocol.Response.SUCCESS) {
this.events.triggerEvent("error", {response: response});
return;
}
switch(response.requestType) {
case 'geocode':
this.events.triggerEvent("locationupdate", {response: response});
break;
}
},
hoverFeature: function(feature, hover) {
this.events.triggerEvent("hoverfeature", {feature: feature, hover: hover});
},
/**
* Wird vom moveend-Event der Karte getriggert und informiert über Änderung des Viewports
* @memberOf BKGWebMap.Control.Geocoder
*/
updateViewPort: function() {
if(!this.useMapExtend) return;
// Kartenausdehnung im Protokoll verwenden
this.protocol.bounds = this.map.getExtent();
// Suggest-Cache leeren
this.protocol.clearCache();
// Autosuggest zurücksetzen
if(this.autocomplete) {
this.autocomplete.clearSuggestions();
}
},
CLASS_NAME: "BKGWebMap.Control.Geocoder"
});
/**
* Factory-Funktion zur Generierung eines Geocoder Steuerelement. Standardmäßig wird dieser mit einem LayerView
* generiert. Falls ein BKGWebMap.Control.SidePanel in der controls-Liste enthalten ist, wird zusätzlich ein
* BKGWebMap.Control.Geocoder.ListView dem Geocoder hinzugefügt.
*
* @param {Array<OpenLayers.Control>} controls - Liste der Steuerelemente, in die die neue erzeugten Steuerelemente
* eingefügt werden sollen.
* @param {object} config - Konfiguration für Steuerelement (s. Konstruktor BKGWebMap.Control.Geocoder).
*/
BKGWebMap.Control.FACTORIES['geocoder'] = function(controls, config) {
if (!config) return;
config = (typeof config === 'boolean') ? {} : config;
// Falls Protokoll nicht explizit gegeben
if(!config.protocol) {
// TODO: umstellen auf Geokodierung
config.protocol = new BKGWebMap.Protocol.Geoindex({url: BKGWebMap.Util.getServiceUrl('gdz_geoindex')});
}
// Views ggf. erstellen
if(!config.views) {
config.views = [new BKGWebMap.Control.Geocoder.LayerView()];
var sidePanel = BKGWebMap.Util.grep(controls, function(c) {return c.CLASS_NAME === 'BKGWebMap.Control.SidePanel'});
if (sidePanel.length > 0) {
var resultsDiv = document.createElement('div');
var resultsDivTitle = document.createElement('h3');
resultsDivTitle.innerHTML = 'Suchergebnisse';
sidePanel[0].content.appendChild(resultsDivTitle );
OpenLayers.Element.addClass(resultsDiv, 'geocoderResults');
sidePanel[0].content.appendChild(resultsDiv);
config.views.push(new BKGWebMap.Control.Geocoder.ListView({div: resultsDiv}));
}
}
// TODO easy setup views
controls.push(new BKGWebMap.Control.Geocoder(config));
};