/*
* Copyright (c) 2012-2014, Dienst Landelijk Gebied - Ministerie van Economische Zaken
*
* Gepubliceerd onder de BSD 2-clause licentie,
* zie https://github.com/MinELenI/CBSviewer/blob/master/LICENSE.md voor de volledige licentie.
*/
/**
* Viewer.
*
* @author mprins
* @return {Viewer} Viewer object
* @class Viewer, de viewer component.
*/
var Viewer = function() {
/**
* Map object, initially null.
*
* @private
* @type {OpenLayers.Map}
*/
var _map = null;
/**
* Toggle vlag voor fullsize functie.
*
* @type {Boolean}
* @private
*/
var _fullSize = false;
/**
* Window resize timout flag.
*
* @type {Boolean}
* @private
*/
var _resizeTimeOut = false;
/**
* Opacity van de voorgrond (WMS) laag.
*
* @type {Number}
* @private
*/
var _opacity = 0.8;
/**
* update het informatie element met feature info.
*
* @param {OpenLayers.Event}
* evt Het featureinfo event
* @private
*/
function _showInfo(evt) {
if (evt.text !== undefined) {
jQuery('#' + config.featureInfoDiv).html(evt.text);
jQuery('#' + config.featureInfoDiv).change();
}
}
/**
* zorgt voor correct afhandelen van viewport resize.
*
* @private
*/
function _resize() {
if (_fullSize) {
var borderW = parseInt(jQuery('#' + this.config.mapDiv).css('borderLeftWidth'), 10)
+ parseInt(jQuery('#' + this.config.mapDiv).css('borderRightWidth'), 10);
var borderH = parseInt(jQuery('#' + this.config.mapDiv).css('borderTopWidth'), 10)
+ parseInt(jQuery('#' + this.config.mapDiv).css('borderBottomWidth'), 10);
// inhoud padding set in css
var headerH = parseInt(jQuery('#' + this.config.mapDiv).parent().parent().css('padding-top'), 10);
var footerH = parseInt(jQuery('#' + this.config.mapDiv).parent().parent().css('padding-bottom'), 10);
var w = jQuery('#' + this.config.mapDiv).parent().width() - borderW;
var h = jQuery(window).height() - headerH - footerH - borderH;
jQuery('#' + this.config.mapDiv).width(w).height(h);
// TODO compute height and remove from here
jQuery('#legenda').css('max-height', jQuery(window).height() - 500);
_map.updateSize();
var vectors = _map.getLayersByClass("OpenLayers.Layer.Vector");
if (vectors.length > 0) {
// in dit geval is er een kaartlaag met een featureinfo lokatie
// verschuif naar die lokatie
var bounds = vectors[0].getDataExtent();
_map.panTo(bounds.getCenterLonLat());
}
}
}
/**
* Stelt de doorzichtigheid van de voorgrond kaart in.
*
* @param alpha
* float waarde tussen 0 1n 1
* @private
*/
function _setOpacity(alpha) {
alpha = parseFloat(alpha);
if (0.09 < alpha && alpha < 0.91) {
_opacity = alpha;
var lyrs = _map.getLayersByClass('OpenLayers.Layer.WMS');
for (var lyr = 0; lyr < lyrs.length; lyr++) {
if (!lyrs[lyr].isBaseLayer) {
lyrs[lyr].setOpacity(_opacity);
}
}
}
}
/**
* event handler voor na de zoomTo functie van deze viewer.
*
* @param lonlat
* {OpenLayers.LonLat} de zoomlokatie
*
* @private
*/
function _afterZoomTo(lonlat) {
_map.getControlsByClass('ClickDrawControl')[0].trigger({
xy : _map.getPixelFromLonLat(lonlat)
});
_map.getControlsByClass('WMSGetFeatureInfo')[0].deactivate();
_map.getControlsByClass('WMSGetFeatureInfo')[0].activate();
_map.events.triggerEvent('click', {
xy : _map.getPixelFromLonLat(lonlat)
});
_map.events.unregister('zoomend', _map, _afterZoomTo);
}
/**
* Update position cookies.
*
* @private
*/
function _updateCookies() {
var _ext = _map.getExtent();
setCookie(COOKIE.X, Math.floor(_ext.getCenterLonLat().lon));
setCookie(COOKIE.Y, Math.floor(_ext.getCenterLonLat().lat));
setCookie(COOKIE.S, Math.floor(_ext.getWidth()));
}
/**
* Publieke interface van deze klasse.
*
* @return {Viewer} publieke methodes
*/
return {
/**
* Constructor, attach to the DOM.
*
* @param {object}
* config Configratie object
* @constructor
*/
init : function(config) {
this.config = config;
OpenLayers.ImgPath = config.imgPath;
OpenLayers.IMAGE_RELOAD_ATTEMPTS = 2;
OpenLayers.Number.decimalSeparator = ",";
// merge any controls met default
jQuery.extend(true, this.config, {
map : {
controls : [],
theme : null
}
});
jQuery(window).unload(function() {
Viewer.destroy();
});
jQuery('#' + this.config.mapDiv).width(this.config.map.width).height(this.config.map.height);
_map = new OpenLayers.Map(this.config.mapDiv, this.config.map);
this.addBaseMap();
this.addControls();
_map.zoomTo(this.config.map.initialZoom);
_map.events.register('moveend', _map, _updateCookies);
// toggle knop voor omschakelen basemap
var aToggle = '<a class="lufo hasTooltip" href="#" id="toggleBaseMap" onclick="Viewer.toggleBaseMap();">'
+ '<span role="tooltip">' + OpenLayers.i18n('KEY_TOGGLE_BASEMAP_TITLE') + '</span>';
aToggle += _map.baseLayer.name === 'topografie' ? OpenLayers.i18n('KEY_TOGGLE_BASEMAP_LUFO') : OpenLayers
.i18n('KEY_TOGGLE_BASEMAP_TOPO');
aToggle += '</a>';
jQuery('#' + config.mapDiv).prepend(aToggle);
if (this.config.toggleSize) {
// toggle knop voor vergroten/verkleinen van de kaart
var aToggleMapSize = '<a class="max hasTooltip" href="#" id="toggleSize" onclick="Viewer.toggleFullSize();">'
+ '<span role="tooltip">' + OpenLayers.i18n('KEY_TOGGLE_SIZE') + '</span></a>';
jQuery('#' + config.mapDiv).prepend(aToggleMapSize);
}
if (this.config.fullSize) {
this.toggleFullSize();
}
jQuery(window).resize(function() {
// aanhaken bij window resize
if (_resizeTimeOut) {
clearTimeout(_resizeTimeOut);
}
_resizeTimeOut = setTimeout(_resize, 200 /* milliseconds */);
});
if (this.config.fgAlphaSlider) {
var aSlider = jQuery('<div id="transparantie" class="transparantieslider"></div>').prependTo(
jQuery('#' + config.mapDiv)).slider({
value : _opacity * 100,
range : 'min',
min : 10,
max : 90,
step : 10,
animate : 'slow',
slide : function(event, ui) {
_setOpacity(ui.value / 100);
jQuery(this).find('a:first').text(ui.value);
jQuery(this).find('a:first').append('<span>' + OpenLayers.i18n('KEY_TRANSP_SLIDER_LABEL', {
'0' : (100 - ui.value)
}) + '</span>');
jQuery(this).find('a:first').addClass('hasTooltip');
}
});
// instellen initiele waarde voor slider GUI
jQuery('#transparantie').find('a:first').addClass('hasTooltip');
jQuery('#transparantie').find('a:first').text((_opacity * 100));
jQuery('#transparantie').find('a:first').append(
'<span role="tooltip">' + OpenLayers.i18n('KEY_TRANSP_SLIDER_LABEL', {
'0' : (100 - (_opacity * 100))
}) + '</span>');
}
},
/**
* Accessor voor de kaart.
*
* @return {OpenLayers.Map} object van deze Viewer of null als het
* object niet is geinitialiseerd
* @deprecated probeer deze niet te gebruiken
*/
getMap : function() {
(window.console && console.warn('Deprecated method called: Viewer::getMap().'));
return _map;
},
/**
* verplaats en zoom de kaart naar de gevraagde locatie.
*
* @param {number}
* x de x coordinaat
* @param {number}
* y de y coordinaat
* @param {number}
* radius straal van het gebied
* @param {boolean}
* withFeatureInfo voert een featureInfo request uit na
* uitvoeren van de zoom en pan actie.
*/
zoomTo : function(x, y, radius, withFeatureInfo) {
var b = new OpenLayers.Bounds(x - radius, y - radius, x + radius, y + radius);
_map.zoomToExtent(b, true);
if (withFeatureInfo) {
// met een zoomend werkt het soms raar, maar met wachten op
// loadend van het eerste wms thema gaat het vaker mis
_map.events.register('zoomend', _map, _afterZoomTo(new OpenLayers.LonLat(x, y)));
}
},
/**
* Controls aan de kaart hangen.
*
* @private
*/
addControls : function() {
_map.addControl(new UpdateLegendControl({
div : jQuery('#' + this.config.legendDiv)[0]
}));
_map.addControl(new OpenLayers.Control.KeyboardDefaults(
/* alleen actief als de kaart focus heeft */
// { observeElement : this.config.mapDiv }
));
_map.addControl(new ZoomControl());
_map.addControl(new OpenLayers.Control.Navigation());
_map.addControl(new OpenLayers.Control.KeyboardClick(
/* alleen actief als de kaart focus heeft */
// { observeElement : this.config.mapDiv }
));
_map.addControl(new WMSGetFeatureInfo({
eventListeners : {
getfeatureinfo : _showInfo
}
}));
_map.addControl(new ClickDrawControl());
_map.addControl(new OpenLayers.Control.ScaleLine({
maxWidth : 200,
bottomOutUnits : '' // geen mi/ft
}));
_map.addControl(new OverviewMap({
mapOptions : {
maxExtent : this.config.map.restrictedExtent,
resolutions : this.config.map.resolutions,
projection : this.config.map.projection,
theme : null
}
}));
},
/**
* cleanup. Moet aangeroepen voor dat een eventueel DOM element van de
* pagina wordt verwijderd. Wordt automatische aangeroepen bij verlaten
* van de pagina.
*/
destroy : function() {
if (_map !== null) {
_map.destroy();
_map = null;
}
},
/**
* Stelt de doorzichtigheid van de voorgrond kaart in.
*
* @param opacity
* float waarde tussen 0 1n 1
*/
setOpacity : function(opacity) {
_setOpacity(opacity);
},
/**
* Voeg WMS toe aan de kaart. Uitgangspunt is dat de WMS transparante
* PNG ondersteund. eerder geladen WMS lagen worden verwijderd
*
* @param {object}
* wmsConfig Een object met WMS parameters. <code>
* {
* 'id' : 'cbs_inwoners_2010_per_hectare',
* 'name': 'Inwoners 2010 per hectare'
* 'url' : 'http://geodata.nationaalgeoregister.nl/cbsvierkanten100m2010/ows',
* 'layers' : 'cbsvierkanten100m2010:cbs_inwoners_2000_per_hectare',
* 'styles' : 'cbsvierkant100m_inwoners_2000'
* }
* </code>
*/
loadWMS : function(wmsConfig) {
this.removeOverlays();
var layer = new OpenLayers.Layer.WMS(wmsConfig.name, wmsConfig.url, {
layers : wmsConfig.layers,
styles : wmsConfig.styles,
version : '1.3.0',
format : 'image/png',
transparent : true
}, {
isBaseLayer : false,
visibility : true,
singleTile : false,
opacity : _opacity
});
if (wmsConfig.hasOwnProperty('zoom')) {
if (_map.getZoom() < parseInt(wmsConfig.zoom))
_map.zoomTo(wmsConfig.zoom);
}
setCookie(COOKIE.mapid, wmsConfig.id);
_map.addLayer(layer);
var fInfoControl = _map.getControlsByClass('WMSGetFeatureInfo');
fInfoControl[0].url = wmsConfig.url;
},
/**
* verwijder de WMS uit de kaart (behalve als het een base layer is).
*
* @param {string}
* wmsLyrName naam van de WMS service
*/
removeWMS : function(wmsLyrName) {
var lyrs = _map.getLayersByName(wmsLyrName);
for (var lyr = 0; lyr < lyrs.length; lyr++) {
if (!lyrs[lyr].isBaseLayer) {
_map.removeLayer(lyrs[lyr]);
lyrs[lyr].destroy();
}
}
},
/**
* verwijder alle overlays. Voorlopig alleen type {OpenLayers.Layer.WMS}
*/
removeOverlays : function() {
// reset featureinfo text
jQuery('#' + config.featureInfoDiv).html(OpenLayers.i18n('KEY_INFO_GEEN_FEATURES'));
// verwijder ikoontjes die de controls tekenen
var lyrs = _map.getLayersByName('ClickDrawControl'), lyr;
for (lyr = 0; lyr < lyrs.length; lyr++) {
lyrs[lyr].removeAllFeatures();
}
lyrs = _map.getLayersByName('OpenLayers.Handler.KeyboardPoint');
for (lyr = 0; lyr < lyrs.length; lyr++) {
lyrs[lyr].removeAllFeatures();
}
// verwijder WMS lagen
lyrs = _map.getLayersByClass('OpenLayers.Layer.WMS');
for (lyr = 0; lyr < lyrs.length; lyr++) {
if (!lyrs[lyr].isBaseLayer) {
_map.removeLayer(lyrs[lyr]);
lyrs[lyr].destroy();
}
}
eraseCookie(COOKIE.mapid);
},
/**
* Afmeting van de kaart aanpassen aan schermbreedte.
*
* @todo hoogte instellen werkt niet omdat de parent hoogte de afmeting
* van de child heeft.
*/
toggleFullSize : function() {
if (_fullSize) {
// terugzetten
jQuery('#' + this.config.mapDiv).width(this.config.map.width).height(this.config.map.height);
jQuery('#toggleSize').toggleClass('restore max');
_fullSize = false;
_map.updateSize();
var vectors = _map.getLayersByClass("OpenLayers.Layer.Vector");
if (vectors.length > 0) {
// in dit geval is er een kaartlaag met een featureinfo
// lokatie verschuif naar die lokatie
var bounds = vectors[0].getDataExtent();
_map.panTo(bounds.getCenterLonLat());
}
} else {
// vergroten
var borderW = parseInt(jQuery('#' + this.config.mapDiv).css('borderLeftWidth'), 10)
+ parseInt(jQuery('#' + this.config.mapDiv).css('borderRightWidth'), 10);
var borderH = parseInt(jQuery('#' + this.config.mapDiv).css('borderTopWidth'), 10)
+ parseInt(jQuery('#' + this.config.mapDiv).css('borderBottomWidth'), 10);
// inhoud padding set in css
var headerH = parseInt(jQuery('#' + this.config.mapDiv).parent().parent().css('padding-top'), 10);
var footerH = parseInt(jQuery('#' + this.config.mapDiv).parent().parent().css('padding-bottom'), 10);
var w = jQuery('#' + this.config.mapDiv).parent().width() - borderW;
var h = jQuery(window).height() - headerH - footerH - borderH;
jQuery('#' + this.config.mapDiv).width(w).height(h);
jQuery('#toggleSize').toggleClass('restore max');
_fullSize = true;
_map.updateSize();
}
},
/**
* Stel de kaart in voor afdrukken.
*/
printPrepare : function() {
if (_fullSize) {
this.toggleFullSize();
}
},
/**
* Toggle basemap.
*/
toggleBaseMap : function() {
var topo = _map.getLayersByName('topografie')[0];
var lufo = _map.getLayersByName('luchtfoto')[0];
if (topo.getVisibility()) {
_map.setBaseLayer(lufo);
jQuery('#toggleBaseMap').text(OpenLayers.i18n('KEY_TOGGLE_BASEMAP_TOPO'));
setCookie(COOKIE.baselyr, 'luchtfoto');
} else {
_map.setBaseLayer(topo);
jQuery('#toggleBaseMap').text(OpenLayers.i18n('KEY_TOGGLE_BASEMAP_LUFO'));
setCookie(COOKIE.baselyr, 'topografie');
}
jQuery('#toggleBaseMap').append('<span>' + OpenLayers.i18n('KEY_TOGGLE_BASEMAP_TITLE') + '</span>');
jQuery('#toggleBaseMap').toggleClass('lufo topo');
},
/**
* set up basemaps.
*
* @private
*/
addBaseMap : function() {
// topo
_map.addLayer(new OpenLayers.Layer.WMTS(jQuery.extend(true, this.config.map.topoWMTS, {
name : 'topografie'
})));
// luchtfoto
_map.addLayer(new OpenLayers.Layer.WMTS(jQuery.extend(true, this.config.map.aerialWMTS, {
name : 'luchtfoto'
})));
if (getCookie(COOKIE.baselyr)) {
_map.setBaseLayer(_map.getLayersByName(getCookie(COOKIE.baselyr))[0]);
}
}
};
}();