/**
* @namespace BKGWebMap.Layer
* @type {object}
*/
BKGWebMap.Layer = BKGWebMap.Layer || {};
/**
* WMS image layer constructor
* @param {WMS} config - Configuration (/layers/baseLayers|overlays/items/WMS and tiles: false)
* @constructor
*/
BKGWebMap.Layer.ImageWMS = function (config) {
this.getLayers = function () {
return config.layers;
};
this.getStyleInfo = function () {
return config.styleInfo;
};
this.getLegendInfo = function () {
return config.legendInfo;
};
this.getTimeInfo = function () {
return config.timeInfo;
};
ol.layer.Image.call(this, config);
};
/**
* WMS tile layer constructor
* @param {WMS} config - Configuration (/layers/baseLayers|overlays/items/WMS and tiles: true)
* @constructor
*/
BKGWebMap.Layer.TileWMS = function (config) {
this.getLayers = function () {
return config.layers;
};
this.getStyleInfo = function () {
return config.styleInfo;
};
this.getLegendInfo = function () {
return config.legendInfo;
};
this.getTimeInfo = function () {
return config.timeInfo;
};
ol.layer.Tile.call(this, config);
};
/**
* WMTS layer constructor
* @param {WMTS} config - Configuration (/layers/baseLayers|overlays/items/WMTS)
* @constructor
*/
BKGWebMap.Layer.WMTS = function (config) {
ol.layer.Tile.call(this, config);
};
/**
* WFS layer constructor
* @param {WFS} config - Configuration (/layers/baseLayers|overlays/items/WFS)
* @constructor
*/
BKGWebMap.Layer.WFS = function (config) {
ol.layer.Vector.call(this, config);
};
/**
* MARKER layer constructor
* @param {MARKER} config - Configuration (/layers/baseLayers|overlays/items/MARKER)
* @constructor
*/
BKGWebMap.Layer.MARKER = function (config) {
ol.layer.Vector.call(this, config);
};
/**
* CSV layer constructor
* @param {CSV} config - Configuration (/layers/baseLayers|overlays/items/CSV)
* @constructor
*/
BKGWebMap.Layer.CSV = function (config) {
ol.layer.Vector.call(this, config);
};
/**
* XLS layer constructor
* @param {XLS} config - Configuration (/layers/baseLayers|overlays/items/XLS)
* @constructor
*/
BKGWebMap.Layer.XLS = function (config) {
ol.layer.Vector.call(this, config);
};
/**
* GPS layer constructor
* @param {GPS} config - Configuration (/layers/baseLayers|overlays/items/GPS)
* @constructor
*/
BKGWebMap.Layer.GPS = function (config) {
ol.layer.Vector.call(this, config);
};
/**
* VECTOR layer constructor
* @param {object} config - Configuration for custom Vector layers imported by user. This class used to persist these layers. The geometry is saved as GeoJSON in this configuration object.
* @constructor
*/
BKGWebMap.Layer.VECTOR = function (config) {
ol.layer.Vector.call(this, config);
};
/**
* GROUP layer constructor
* @param {GROUP} config - (/layers/baseLayers/items/GPS)
* @constructor
*/
BKGWebMap.Layer.GROUP = function (config) {
ol.layer.Group.call(this, config);
};
/**
* NONE (Empty) layer constructor
* @param {NONE} config - Configuration (/layers/baseLayers/items/NONE)
* @constructor
*/
BKGWebMap.Layer.NONE = function (config) {
ol.layer.Image.call(this, config);
};
/**
* Create WMS layer
* @typedef {function} LAYER_FACTORIES_WMS
* @param {BKGWebMap.ParseConfig} createConfig - BKGWebMap.ParseConfig object
* @param {object} map - Map object
* @param {WMS} config - WMS configuration
* @param {object} styles - Object with styles ({@link symbol_style}|{@link custom_style})
* @param {boolean} bkg - This layer is generated from a BKG Layer
* @param {function} callback - Callback function. It will be called when all information of layer are parsed.
* @returns {object}
*/
/**
* Create WMTS layer
* @typedef {function} LAYER_FACTORIES_WMTS
* @param {BKGWebMap.ParseConfig} createConfig - BKGWebMap.ParseConfig object
* @param {object} map - Map object
* @param {WMTS} config - WMTS configuration
* @param {object} styles - Object with styles ({@link symbol_style}|{@link custom_style})
* @param {boolean} bkg - This layer is generated from a BKG Layer
* @param {function} callback - Callback function. It will be called when all information of layer are parsed.
* @returns {object}
*/
/**
* Create WFS layer
* @typedef {function} LAYER_FACTORIES_WFS
* @param {BKGWebMap.ParseConfig} createConfig - BKGWebMap.ParseConfig object
* @param {object} map - Map object
* @param {WFS} config - WFS configuration
* @param {object} styles - Object with styles ({@link symbol_style}|{@link custom_style})
* @param {boolean} bkg - This layer is generated from a BKG Layer
* @param {function} callback - Callback function. It will be called when all information of layer are parsed.
* @returns {object}
*/
/**
* Create MARKER layer
* @typedef {function} LAYER_FACTORIES_MARKER
* @param {BKGWebMap.ParseConfig} createConfig - BKGWebMap.ParseConfig object
* @param {object} map - Map object
* @param {MARKER} config - MARKER configuration
* @param {object} styles - Object with styles ({@link symbol_style}|{@link custom_style})
* @param {boolean} bkg - This layer is generated from a BKG Layer
* @param {function} callback - Callback function. It will be called when all information of layer are parsed.
* @returns {object}
*/
/**
* Create CSV layer
* @typedef {function} LAYER_FACTORIES_MARKER
* @param {BKGWebMap.ParseConfig} createConfig - BKGWebMap.ParseConfig object
* @param {object} map - Map object
* @param {CSV} config - CSV configuration
* @param {object} styles - Object with styles ({@link symbol_style}|{@link custom_style})
* @param {boolean} bkg - This layer is generated from a BKG Layer
* @param {function} callback - Callback function. It will be called when all information of layer are parsed.
* @returns {object}
*/
/**
* Create XLS layer
* @typedef {function} LAYER_FACTORIES_XLS
* @param {BKGWebMap.ParseConfig} createConfig - BKGWebMap.ParseConfig object
* @param {object} map - Map object
* @param {XLS} config - XLS configuration
* @param {object} styles - Object with styles ({@link symbol_style}|{@link custom_style})
* @param {boolean} bkg - This layer is generated from a BKG Layer
* @param {function} callback - Callback function. It will be called when all information of layer are parsed.
* @returns {object}
*/
/**
* Create GPS layer
* @typedef {function} LAYER_FACTORIES_GPS
* @param {BKGWebMap.ParseConfig} createConfig - BKGWebMap.ParseConfig object
* @param {object} map - Map object
* @param {GPS} config - GPS configuration
* @param {object} styles - Object with styles ({@link symbol_style}|{@link custom_style})
* @param {boolean} bkg - This layer is generated from a BKG Layer
* @param {function} callback - Callback function. It will be called when all information of layer are parsed.
* @returns {object}
*/
/**
* Create VECTOR layer
* @typedef {function} LAYER_FACTORIES_VECTOR
* @param {BKGWebMap.ParseConfig} createConfig - BKGWebMap.ParseConfig object
* @param {object} map - Map object
* @param {object} config - VECTOR configuration
* @param {object} styles - Object with styles ({@link symbol_style}|{@link custom_style})
* @param {boolean} bkg - This layer is generated from a BKG Layer
* @param {function} callback - Callback function. It will be called when all information of layer are parsed.
* @returns {object}
*/
/**
* Create GROUP layer
* @typedef {function} LAYER_FACTORIES_GROUP
* @param {BKGWebMap.ParseConfig} createConfig - BKGWebMap.ParseConfig object
* @param {object} map - Map object
* @param {GROUP} config - GROUP configuration
* @param {object} styles - Object with styles ({@link symbol_style}|{@link custom_style})
* @param {boolean} bkg - This layer is generated from a BKG Layer
* @param {function} callback - Callback function. It will be called when all information of layer are parsed.
* @returns {object}
*/
/**
* Create BKG layer
* @typedef {function} LAYER_FACTORIES_BKG
* @param {BKGWebMap.ParseConfig} createConfig - BKGWebMap.ParseConfig object
* @param {object} map - Map object
* @param {BKG} config - BKG configuration
* @param {object} styles - Object with styles ({@link symbol_style}|{@link custom_style})
* @param {boolean} bkg - This layer is generated from a BKG Layer
* @param {function} callback - Callback function. It will be called when all information of layer are parsed.
* @returns {object}
*/
/**
* Create NONE (empty) layer
* @typedef {function} LAYER_FACTORIES_NONE
* @param {BKGWebMap.ParseConfig} createConfig - BKGWebMap.ParseConfig object
* @param {object} map - Map object
* @param {NONE} config - NONE configuration
* @param {object} styles - Object with styles ({@link symbol_style}|{@link custom_style})
* @param {boolean} bkg - This layer is generated from a BKG Layer
* @param {function} callback - Callback function. It will be called when all information of layer are parsed.
* @returns {object}
*/
/**
* Factory functions to generate layers
* @type {object}
* @memberof BKGWebMap.Layer
* @property {function} WMS - Method to create WMS layer. See {@link LAYER_FACTORIES_WMS}
* @property {function} WMTS - Method to create WMTS layer. See {@link LAYER_FACTORIES_WMTS}
* @property {function} WFS - Method to create WFS layer. See {@link LAYER_FACTORIES_WFS}
* @property {function} MARKER - Method to create MARKER layer. See {@link LAYER_FACTORIES_MARKER}
* @property {function} CSV - Method to create CSV layer. See {@link LAYER_FACTORIES_MARKER}
* @property {function} XLS - Method to create XLS layer. See {@link LAYER_FACTORIES_XLS}
* @property {function} GPS - Method to create GPS layer. See {@link LAYER_FACTORIES_GPS}
* @property {function} VECTOR - Method to create VECTOR layer. See {@link LAYER_FACTORIES_VECTOR}
* @property {function} GROUP - Method to create GROUP layer. See {@link LAYER_FACTORIES_GROUP}
* @property {function} BKG - Method to create BKG layer. See {@link LAYER_FACTORIES_BKG}
* @property {function} NONE - Method to create NONE layer. See {@link LAYER_FACTORIES_NONE}
*
*/
BKGWebMap.Layer.FACTORIES = {
WMS: function (createConfig, map, config, styles, bkg, callback) {
var originalConfig = BKGWebMap.Util.deepCopy(config);
delete originalConfig.isBaseLayer;
config.originalConfig = originalConfig;
config.uniqueId = BKGWebMap.Util.uniqueId();
if (!config.id) {
config.id = BKGWebMap.Util.generateLayerId();
}
// For export json
if (config.bkg) {
bkg = config.bkg;
} else if (bkg) {
originalConfig.bkg = bkg;
}
var i;
var source;
var url = config.url;
var sourceParams = {};
var version = BKGWebMap.LAYERS.WMS.VERSION;
var projection = BKGWebMap.PROJECTION;
var copyright = '';
var styleInfo = {};
var legendInfo = {};
var timeInfo = {};
function defineLayer(source, config, extent) {
var layer;
if (config.tiles === false) {
layer = new BKGWebMap.Layer.ImageWMS(config);
} else {
layer = new BKGWebMap.Layer.TileWMS(config);
}
if (extent) {
layer.extent = extent;
}
layer.setSource(source);
// Update request according to resolution limits
resolutionLimitsSublayers(layer, config);
return callback(layer);
}
function resolutionLimitsSublayers(layer, config) {
if (BKGWebMap.Util.hasNestedProperty(layer.getProperties(), 'originalConfig.layers')) {
config = layer.getProperties().originalConfig;
}
var updateParams;
for (var i = 0; i < config.layers.length; i++) {
if (config.layers[i].minResolution || config.layers[i].maxResolution) {
updateParams = true;
}
}
if (updateParams) {
map.getView().on('change:resolution', function () {
var mapResolution = map.getView().getResolution();
var visibility = config.visibility === undefined ? true : config.visibility;
var sublayersArray = config.layers.reduce(function (filtered, singleLayer) {
var checkLayerMinResolution = !((singleLayer.minResolution && mapResolution < singleLayer.minResolution));
var checkLayerMaxResolution = !((singleLayer.maxResolution && mapResolution > singleLayer.maxResolution));
if (singleLayer.visibility !== false && checkLayerMinResolution && checkLayerMaxResolution) {
filtered.push(singleLayer.layer);
}
return filtered;
}, []);
var sublayersStyleArray = config.layers.reduce(function (filtered, singleLayer) {
var checkLayerMinResolution = !((singleLayer.minResolution && mapResolution < singleLayer.minResolution));
var checkLayerMaxResolution = !((singleLayer.maxResolution && mapResolution > singleLayer.maxResolution));
if (singleLayer.visibility !== false && checkLayerMinResolution && checkLayerMaxResolution) {
filtered.push(singleLayer.style);
}
return filtered;
}, []);
layer.getSource().updateParams({ LAYERS: sublayersArray.join(), STYLES: sublayersStyleArray.join() });
if (!sublayersArray.length) {
layer.setVisible(false);
} else {
layer.setVisible(visibility);
}
});
}
}
// Visible
config.visible = BKGWebMap.LAYERS.WMS.VISIBLE;
if (typeof config.visibility === 'boolean' && config.visibility === false) {
config.visible = config.visibility;
}
delete config.visibility;
// Copyright
if (config.copyright && typeof config.copyright === 'string' && config.copyright !== '') {
copyright = config.copyright;
}
// Source -> URL
if (typeof url !== 'string' || url === '') {
window.console.log(BKGWebMap.ERROR.wrongUrl + config.type);
return callback(undefined);
}
// If function is called through a BKG layer, try to use UUID
if (bkg && BKGWebMap.SECURITY.UUID) {
url = url + '__' + BKGWebMap.SECURITY.UUID;
}
// Source -> version
if (config.version && (config.version === '1.1.0' || config.version === '1.1.1')) {
version = config.version;
}
// Source -> Projection (srsName)
if (config.srsName && typeof config.srsName === 'string' && config.srsName !== '') {
projection = config.srsName;
}
if (!config.layers || !(config.layers instanceof Array)) {
return callback(undefined);
}
// Add visibility, unique id and selectStyle url for sublayers. Get default legend URL.
for (i = 0; i < config.layers.length; i++) {
if (!Object.prototype.hasOwnProperty.call(config.layers[i], 'visibility')) {
config.layers[i].visibility = BKGWebMap.LAYERS.WMS.VISIBLE;
}
if (!Object.prototype.hasOwnProperty.call(config.layers[i], 'selectStyle')) {
config.layers[i].selectStyle = BKGWebMap.LAYERS.WMS.SELECT_STYLE;
}
config.layers[i].uniqueId = BKGWebMap.Util.uniqueId();
if (config.layers[i].legendUrl && (typeof config.layers[i].legendUrl === 'string' || config.layers[i].legendUrl instanceof String) && config.layers[i].legendUrl !== '') {
legendInfo[config.layers[i].layer] = config.layers[i].legendUrl;
} else {
legendInfo[config.layers[i].layer] = '';
}
}
// Filter sublayers. Request only the ones that should be visible
var mapResolution = map.getView().getResolution();
var sublayersArray = config.layers.reduce(function (filtered, singleLayer) {
var checkLayerMinResolution = !((singleLayer.minResolution && mapResolution < singleLayer.minResolution));
var checkLayerMaxResolution = !((singleLayer.maxResolution && mapResolution > singleLayer.maxResolution));
if (singleLayer.visibility !== false && checkLayerMinResolution && checkLayerMaxResolution) {
filtered.push(singleLayer.layer);
}
return filtered;
}, []);
// Filter styles
var sublayersStyleArray = config.layers.reduce(function (filtered, singleLayer) {
var checkLayerMinResolution = !((singleLayer.minResolution && mapResolution < singleLayer.minResolution));
var checkLayerMaxResolution = !((singleLayer.maxResolution && mapResolution > singleLayer.maxResolution));
if (singleLayer.visibility !== false && checkLayerMinResolution && checkLayerMaxResolution) {
filtered.push(singleLayer.style);
}
return filtered;
}, []);
// Use all sublayers to get layer extent
var allSublayersArray = config.layers.reduce(function (filtered, singleLayer) {
filtered.push(singleLayer.layer);
return filtered;
}, []);
// Source params (If the user has tried to use a params property in config, use it! Hidden feature..)
if (config.params && (typeof config.params === 'object' && config.params.constructor === Object)) {
sourceParams = config.params;
} else {
sourceParams = {
LAYERS: sublayersArray.join(),
VERSION: version,
STYLES: sublayersStyleArray.join()
};
}
// add additional request parameters if present in config
var extraSourceParams = ['bgcolor'];
for (i = 0; i < extraSourceParams.length; i++) {
var key = extraSourceParams[i];
if (config[key]) {
sourceParams[key] = config[key];
}
}
// Object with source options
var sourceOptions = {
url: url,
params: sourceParams,
projection: projection
};
// Source -> All other possible source OpenLayers options should be added silently to source class
// They are not part of BKG WebMap Documentation.
var extraSourceOptionsImage = [
'attributions',
'crossOrigin',
'hidpi',
'serverType',
'imageLoadFunction',
'logo',
'ratio',
'resolutions'
];
var extraSourceOptionsTile = [
'attributions',
'cacheSize',
'crossOrigin',
'gutter',
'hidpi',
'logo',
'tileClass',
'tileGrid',
'reprojectionErrorThreshold',
'serverType',
'tileLoadFunction',
'urls',
'wrapX',
'transition'
];
if (Object.prototype.hasOwnProperty.call(config, 'tiles') && config.tiles === false) {
for (i = 0; i < extraSourceOptionsImage.length; i++) {
if (config[extraSourceOptionsImage[i]]) {
sourceOptions[extraSourceOptionsImage[i]] = config[extraSourceOptionsImage[i]];
}
}
// Image WMS
ol.inherits(BKGWebMap.Layer.ImageWMS, ol.layer.Image);
source = new ol.source.ImageWMS(sourceOptions);
} else {
for (i = 0; i < extraSourceOptionsTile.length; i++) {
if (config[extraSourceOptionsTile[i]]) {
sourceOptions[extraSourceOptionsTile[i]] = config[extraSourceOptionsTile[i]];
}
}
// Tile WMS
ol.inherits(BKGWebMap.Layer.TileWMS, ol.layer.Tile);
source = new ol.source.TileWMS(sourceOptions);
}
function parseLayersInfoWMS(arrayLayers, config, extentParsed, mapEPSG, extent, mapProjection) {
for (var i = 0; i < arrayLayers.length; i++) {
if (arrayLayers[i].Layer && arrayLayers[i].Layer instanceof Array && arrayLayers[i].Layer.length) {
parseLayersInfoWMS(arrayLayers[i].Layer, config, extentParsed, mapEPSG, extent, mapProjection);
} else if (allSublayersArray.indexOf(arrayLayers[i].Name) !== -1) {
// extent
if (arrayLayers[i].BoundingBox instanceof Array) {
var tempBbox = arrayLayers[i].BoundingBox;
for (var x = 0; x < tempBbox.length; x++) {
if (tempBbox[x].crs === mapEPSG && tempBbox[x].extent instanceof Array) {
ol.extent.extend(extent, tempBbox[x].extent);
extentParsed = true;
}
}
}
if (!extentParsed && arrayLayers[i].EX_GeographicBoundingBox instanceof Array) {
var tempExtent = ol.proj.transformExtent(arrayLayers[i].EX_GeographicBoundingBox, 'EPSG:4326', mapProjection);
ol.extent.extend(extent, tempExtent);
}
}
// Style
for (var k = 0; k < config.layers.length; k++) {
if (config.layers[k].layer === arrayLayers[i].Name) {
if (arrayLayers[i].Style && arrayLayers[i].Style instanceof Array) {
styleInfo[arrayLayers[i].Name] = arrayLayers[i].Style;
// Get legend url
if (legendInfo[arrayLayers[i].Name] === '') {
legendInfo[arrayLayers[i].Name] = {};
for (var j = 0; j < arrayLayers[i].Style.length; j++) {
if (arrayLayers[i].Style[j].LegendURL) {
legendInfo[arrayLayers[i].Name][arrayLayers[i].Style[j].Name] = arrayLayers[i].Style[j].LegendURL[0].OnlineResource;
}
}
}
}
if (config.time && config.time.active && arrayLayers[i].Dimension && arrayLayers[i].Dimension instanceof Array) {
for (var d = 0; d < arrayLayers[i].Dimension.length; d++) {
if (arrayLayers[i].Dimension[d].name === 'time') {
timeInfo[arrayLayers[i].Name] = arrayLayers[i].Dimension[d];
}
}
}
}
}
}
}
// GetCapabilities to get extent and copyright
var xhr = new XMLHttpRequest();
xhr.open('GET', url + '?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities');
xhr.onload = function () {
if (xhr.status === 200) {
var parser = new ol.format.WMSCapabilities();
var result = parser.read(xhr.responseText);
var mapProjection = map.getView().getProjection();
var mapEPSG = mapProjection.getCode();
var extent = ol.extent.createEmpty();
var extentParsed = false;
if (BKGWebMap.Util.hasNestedProperty(result, 'Capability.Layer.Layer')) {
if (result.Capability.Layer.Layer && result.Capability.Layer.Layer instanceof Array && result.Capability.Layer.Layer.length > 0) {
var arrayLayers = result.Capability.Layer.Layer;
parseLayersInfoWMS(arrayLayers, config, extentParsed, mapEPSG, extent, mapProjection);
}
}
if (BKGWebMap.Util.hasNestedProperty(result, 'Capability.Request.GetFeatureInfo.Format') && result.Capability.Request.GetFeatureInfo.Format.length) {
var formats = result.Capability.Request.GetFeatureInfo.Format;
for (var m = 0; m < BKGWebMap.GETFEATUREINFO_FORMATS.length; m++) {
if (formats.indexOf(BKGWebMap.GETFEATUREINFO_FORMATS[m]) !== -1) {
config.GetFeatureInfoFormat = BKGWebMap.GETFEATUREINFO_FORMATS[m];
break;
}
}
}
if (extent.indexOf(Infinity) !== -1) {
extent = null;
}
if (!copyright) {
if (BKGWebMap.Util.hasNestedProperty(result, 'Service.Fees') && result.Service.Fees !== '' && result.Service.Fees !== 'NONE') {
copyright += result.Service.Fees + ' ';
}
if (BKGWebMap.Util.hasNestedProperty(result, 'Service.AccessConstraints') && result.Service.AccessConstraints !== '' && result.Service.AccessConstraints !== 'NONE') {
copyright += result.Service.AccessConstraints + ' ';
}
}
config.styleInfo = styleInfo;
config.legendInfo = legendInfo;
config.timeInfo = timeInfo;
if (copyright) {
config.copyright = copyright;
}
defineLayer(source, config, extent);
}
};
xhr.onerror = function () {
defineLayer(source, config);
};
xhr.send();
},
WMTS: function (createConfig, map, config, styles, bkg, callback) {
var originalConfig = BKGWebMap.Util.deepCopy(config);
delete originalConfig.isBaseLayer;
config.originalConfig = originalConfig;
config.uniqueId = BKGWebMap.Util.uniqueId();
if (!config.id) {
config.id = BKGWebMap.Util.generateLayerId();
}
// For export json
if (config.bkg) {
bkg = config.bkg;
} else if (bkg) {
originalConfig.bkg = bkg;
}
var i;
var url = config.url;
var wmtsLayer = config.layer;
var copyright = '';
// Source -> Projection (srsName)
var layerProjection;
if (config.srsName && typeof config.srsName === 'string' && config.srsName !== '') {
layerProjection = config.srsName;
} else {
layerProjection = map.getView().getProjection();
}
function defineLayer(sourceOptions, extent) {
var source = new ol.source.WMTS(sourceOptions);
ol.inherits(BKGWebMap.Layer.WMTS, ol.layer.Tile);
var layer = new BKGWebMap.Layer.WMTS(config);
if (extent) {
extent = ol.proj.transformExtent(extent, 'EPSG:4326', layerProjection);
layer.extent = extent;
}
layer.setSource(source);
return callback(layer);
}
// Layer
if (typeof wmtsLayer !== 'string' || wmtsLayer === '') {
window.console.log(BKGWebMap.ERROR.wmtsLayerName);
return callback(undefined);
}
// Visible
config.visible = BKGWebMap.LAYERS.WMTS.VISIBLE;
if (typeof config.visibility === 'boolean' && config.visibility === false) {
config.visible = config.visibility;
}
delete config.visibility;
// Copyright
if (config.copyright && typeof config.copyright === 'string' && config.copyright !== '') {
copyright = config.copyright;
}
// Source -> URL
var xhr;
if (typeof url !== 'string' || url === '') {
window.console.log(BKGWebMap.ERROR.wrongUrl + config.type);
return callback(undefined);
} else if (url.slice(url.length - 4, url.length) === '.xml') {
// If the link ends with .xml, then access WMTS from a GetCapabilities response
xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function () {
if (xhr.status === 200) {
var parser = new ol.format.WMTSCapabilities();
var result = parser.read(xhr.responseText);
var extent;
var legendUrl;
if (BKGWebMap.Util.hasNestedProperty(result, 'Contents.Layer') && result.Contents.Layer.length) {
if (result.Contents.Layer[0].WGS84BoundingBox && result.Contents.Layer[0].WGS84BoundingBox.length === 4) {
for (var j = 0; j < result.Contents.Layer.length; j++) {
var layerConfig = result.Contents.Layer[j];
if (wmtsLayer !== layerConfig.Identifier) {
continue;
}
if (layerConfig.WGS84BoundingBox && layerConfig.WGS84BoundingBox.length === 4) {
extent = layerConfig.WGS84BoundingBox;
}
}
}
}
if (!copyright) {
if (BKGWebMap.Util.hasNestedProperty(result, 'ServiceIdentification.Fees') && result.ServiceIdentification.Fees !== '' && result.ServiceIdentification.Fees !== 'NONE') {
copyright += result.ServiceIdentification.Fees + ' ';
}
if (BKGWebMap.Util.hasNestedProperty(result, 'ServiceIdentification.AccessConstraints') && result.ServiceIdentification.AccessConstraints !== '' && result.ServiceIdentification.AccessConstraints !== 'NONE') {
copyright += result.ServiceIdentification.AccessConstraints + ' ';
}
}
if (!config.legendUrl && BKGWebMap.Util.hasNestedProperty(result, 'Contents.Layer') && result.Contents.Layer.length) {
if (result.Contents.Layer[0].Style && result.Contents.Layer[0].Style.length && result.Contents.Layer[0].Style[0].LegendURL && result.Contents.Layer[0].Style[0].LegendURL.length) {
legendUrl = result.Contents.Layer[0].Style[0].LegendURL[0].href;
}
}
if (legendUrl) {
config.legendUrl = legendUrl;
}
var options = ol.source.WMTS.optionsFromCapabilities(result, {
layer: wmtsLayer,
matrixSet: config.matrixSet
});
// If function is called through a BKG layer, try to use UUID
if (bkg && BKGWebMap.SECURITY.UUID && options.urls instanceof Array) {
for (var i = 0; i < options.urls.length; i++) {
options.urls[i] = options.urls[i].replace('/tile/', '__' + BKGWebMap.SECURITY.UUID + '/tile/');
}
}
if (copyright) {
config.copyright = copyright;
}
defineLayer(options, extent);
} else if (xhr.status !== 200) {
return callback(undefined);
}
};
xhr.onerror = function () {
window.console.log(BKGWebMap.ERROR.wmtsGetCapabilities);
return callback(undefined);
};
xhr.send();
} else {
// Create WMTS request manually
var projection = BKGWebMap.PROJECTION;
var style = BKGWebMap.LAYERS.WMTS.DEFAULTSTYLE;
var tileGrid;
// Source -> Projection (srsName)
if (config.srsName && typeof config.srsName === 'string' && config.srsName !== '') {
projection = config.srsName;
}
if (!config.tileGrid || typeof config.tileGrid !== 'object') {
window.console.log(BKGWebMap.ERROR.wmtsTileGrid);
return callback(undefined);
} else if (config.tileGrid instanceof ol.tilegrid.WMTS) {
tileGrid = config.tileGrid;
} else {
tileGrid = new ol.tilegrid.WMTS(config.tileGrid);
}
if (config.style && typeof config.style === 'string' && config.style !== '') {
style = config.style;
}
// If function is called through a BKG layer, try to use UUID
if (bkg && BKGWebMap.SECURITY.UUID) {
url = url + '__' + BKGWebMap.SECURITY.UUID;
}
// Object with source options
var sourceOptions = {
url: url,
layer: wmtsLayer,
projection: projection,
tileGrid: tileGrid,
style: style
};
// All other possible WMTS source options, even those not included in Documentation
var extraSourceOptions = [
'attributions',
'cacheSize',
'crossOrigin',
'logo',
'reprojectionErrorThreshold',
'requestEncoding',
'tileClass',
'tilePixelRatio',
'version',
'format',
'matrixSet',
'dimensions',
'tileLoadFunction',
'urls',
'wrapX',
'transition'
];
for (i = 0; i < extraSourceOptions.length; i++) {
if (config[extraSourceOptions[i]]) {
sourceOptions[extraSourceOptions[i]] = config[extraSourceOptions[i]];
}
}
// GetCapabilities to get extent
xhr = new XMLHttpRequest();
xhr.open('GET', url + '/1.0.0/WMTSCapabilities.xml');
xhr.onload = function () {
if (xhr.status === 200) {
var parser = new ol.format.WMTSCapabilities();
var result = parser.read(xhr.responseText);
var extent;
var legendUrl;
if (BKGWebMap.Util.hasNestedProperty(result, 'Contents.Layer') && result.Contents.Layer.length) {
if (result.Contents.Layer[0].WGS84BoundingBox && result.Contents.Layer[0].WGS84BoundingBox.length === 4) {
for (var j = 0; j < result.Contents.Layer.length; j++) {
var layerConfig = result.Contents.Layer[j];
if (wmtsLayer !== layerConfig.Identifier) {
continue;
}
if (layerConfig.WGS84BoundingBox && layerConfig.WGS84BoundingBox.length === 4) {
extent = layerConfig.WGS84BoundingBox;
}
}
}
}
if (!copyright) {
if (BKGWebMap.Util.hasNestedProperty(result, 'ServiceIdentification.Fees') && result.ServiceIdentification.Fees !== '' && result.ServiceIdentification.Fees !== 'NONE') {
copyright += result.ServiceIdentification.Fees + ' ';
}
if (BKGWebMap.Util.hasNestedProperty(result, 'ServiceIdentification.AccessConstraints') && result.ServiceIdentification.AccessConstraints !== '' && result.ServiceIdentification.AccessConstraints !== 'NONE') {
copyright += result.ServiceIdentification.AccessConstraints + ' ';
}
}
if (copyright) {
config.copyright = copyright;
}
if (!config.legendUrl && BKGWebMap.Util.hasNestedProperty(result, 'Contents.Layer') && result.Contents.Layer.length) {
if (result.Contents.Layer[0].Style.length && result.Contents.Layer[0].Style[0].LegendURL.length) {
legendUrl = result.Contents.Layer[0].Style[0].LegendURL[0].href;
}
}
if (legendUrl) {
config.legendUrl = legendUrl;
}
defineLayer(sourceOptions, extent);
}
};
xhr.onerror = function () {
defineLayer(sourceOptions);
};
xhr.send();
}
},
WFS: function (createConfig, map, config, styles, bkg, callback) {
var originalConfig = BKGWebMap.Util.deepCopy(config);
delete originalConfig.isBaseLayer;
config.originalConfig = originalConfig;
config.uniqueId = BKGWebMap.Util.uniqueId();
if (!config.id) {
config.id = BKGWebMap.Util.generateLayerId();
}
// Style
var styleObject = BKGWebMap.Style.createStyles([BKGWebMap.DEFAULT_STYLE]);
var style = styleObject['bkgwebmap-defaultstyle'];
if (styles && Object.prototype.hasOwnProperty.call(styles, config.style)) {
config.styleName = config.style;
style = styles[config.style];
}
config.style = style;
var copyright = '';
var url = config.url;
var wfsDataProjection = BKGWebMap.PROJECTION;
var mapProjection = map.getView().getProjection().getCode();
var version = BKGWebMap.LAYERS.WFS.VERSION;
var format = BKGWebMap.LAYERS.WFS.FORMAT;
var edit = BKGWebMap.LAYERS.WFS.EDIT;
var typename = config.typename;
var tiles = BKGWebMap.LAYERS.WFS.TILES;
var formats = {
GEOJSON: {
olClass: new ol.format.GeoJSON(),
outputFormat: 'application/json'
},
GML2: {
olClass: new ol.format.GML2(),
outputFormat: 'gml2'
},
GML3: {
olClass: new ol.format.WFS(),
outputFormat: 'gml3'
}
};
// Copyright
if (config.copyright && typeof config.copyright === 'string' && config.copyright !== '') {
copyright = config.copyright;
}
// Edit is always false for WFS
config.edit = edit;
// Source -> URL
if (typeof url !== 'string' || url === '') {
window.console.log(BKGWebMap.ERROR.wrongUrl + config.type);
return callback(undefined);
}
// Source -> Projection (srsName)
if (config.srsName && typeof config.srsName === 'string' && config.srsName !== '') {
wfsDataProjection = config.srsName;
}
// Source -> typename
if (typeof typename !== 'string' || url === '') {
window.console.log(BKGWebMap.ERROR.wfsTypename);
return callback(undefined);
}
// Be sure to use only once '?' in url
if (url.charAt(url.length - 1) !== '?') {
url += '?';
}
// Source -> version
if (config.version && typeof config.version === 'string' && config.version !== '') {
version = config.version;
}
// Source -> format
if (config.format && (config.format === 'GML2' || config.format === 'GML3' || config.format === 'GEOJSON')) {
format = config.format;
}
// Tiles
if (typeof config.tiles === 'boolean') {
tiles = config.tiles;
}
// Visible
config.visible = BKGWebMap.LAYERS.WFS.VISIBLE;
if (typeof config.visibility === 'boolean' && config.visibility === false) {
config.visible = config.visibility;
}
delete config.visibility;
ol.inherits(BKGWebMap.Layer.WFS, ol.layer.Vector);
var layer = new BKGWebMap.Layer.WFS(config);
var bboxDataProjection;
if (version === '1.0.0') {
bboxDataProjection = '';
} else {
bboxDataProjection = ',' + wfsDataProjection;
}
var strategy;
if (tiles) {
strategy = ol.loadingstrategy.tile(ol.tilegrid.createXYZ());
} else {
strategy = ol.loadingstrategy.bbox;
}
var typenameKey = (version === '2.0.0') ? 'typenames' : 'typename';
var sourceOptions = {
format: formats[format].olClass,
loader: function (extent) {
var extentTransform = ol.proj.transformExtent(extent, mapProjection, wfsDataProjection);
var urlString = [
url,
'service=WFS',
'version=' + version,
'request=GetFeature',
typenameKey + '=' + typename,
'outputFormat=' + formats[format].outputFormat,
'srsname=' + wfsDataProjection,
'bbox=' + extentTransform.join(',') + bboxDataProjection
].join('&');
var xhr = new XMLHttpRequest();
xhr.open('GET', urlString);
var onError = function () {
source.removeLoadedExtent(extent);
return undefined;
};
xhr.onerror = onError;
xhr.onload = function () {
if (xhr.status === 200) {
source.addFeatures(source.getFormat().readFeatures(xhr.responseText, {
dataProjection: wfsDataProjection,
featureProjection: mapProjection
}));
} else {
onError();
}
};
xhr.send();
},
strategy: strategy
};
// All other possible WFS source options, even those not included in Documentation
var extraSourceOptions = [
'attributions',
'logo',
'overlaps',
'useSpatialIndex',
'wrapX'
];
for (var i = 0; i < extraSourceOptions.length; i++) {
if (config[extraSourceOptions[i]]) {
sourceOptions[extraSourceOptions[i]] = config[extraSourceOptions[i]];
}
}
var source = new ol.source.Vector(sourceOptions);
layer.setSource(source);
// GetCapabilities to get copyright
var xhr = new XMLHttpRequest();
xhr.open('GET', url + 'REQUEST=GetCapabilities&VERSION=1.3.0&SERVICE=wfs');
xhr.onload = function () {
if (xhr.status === 200) {
var parser = new DOMParser();
var resultXml = parser.parseFromString(xhr.responseText, 'text/xml');
var result = BKGWebMap.Util.xmlToJson(resultXml);
var extent = new ol.extent.createEmpty();
if (BKGWebMap.Util.hasNestedProperty(result, 'wfs:WFS_Capabilities.FeatureTypeList.FeatureType') && result['wfs:WFS_Capabilities'].FeatureTypeList.FeatureType instanceof Array) {
var featuresWFS = result['wfs:WFS_Capabilities'].FeatureTypeList.FeatureType;
for (var i = 0; i < featuresWFS.length; i++) {
if (BKGWebMap.Util.hasNestedProperty(featuresWFS[i], 'ows:WGS84BoundingBox.ows:LowerCorner.#text') && BKGWebMap.Util.hasNestedProperty(featuresWFS[i], 'ows:WGS84BoundingBox.ows:UpperCorner.#text')) {
var extentFeature = [parseFloat(featuresWFS[i]['ows:WGS84BoundingBox']['ows:LowerCorner']['#text'].split(' ')[0]), parseFloat(featuresWFS[i]['ows:WGS84BoundingBox']['ows:LowerCorner']['#text'].split(' ')[1]), parseFloat(featuresWFS[i]['ows:WGS84BoundingBox']['ows:UpperCorner']['#text'].split(' ')[0]), parseFloat(featuresWFS[i]['ows:WGS84BoundingBox']['ows:UpperCorner']['#text'].split(' ')[1])];
var transformExtent = ol.proj.transformExtent(extentFeature, 'EPSG:4326', mapProjection);
extent = new ol.extent.extend(extent, transformExtent);
}
}
}
layer.fullExtent = extent;
if (!copyright) {
if (BKGWebMap.Util.hasNestedProperty(result, 'wfs:WFS_Capabilities.ows:ServiceIdentification.ows:Fees.#text') && result['wfs:WFS_Capabilities']['ows:ServiceIdentification']['ows:Fees']['#text'] !== '' && result['wfs:WFS_Capabilities']['ows:ServiceIdentification']['ows:Fees']['#text'] !== 'NONE') {
copyright += result['wfs:WFS_Capabilities']['ows:ServiceIdentification']['ows:Fees']['#text'] + ' ';
} else if (BKGWebMap.Util.hasNestedProperty(result, 'WFS_Capabilities.ows:ServiceIdentification.ows:Fees.#text') && result.WFS_Capabilities['ows:ServiceIdentification']['ows:Fees']['#text'] !== '' && result.WFS_Capabilities['ows:ServiceIdentification']['ows:Fees']['#text'] !== 'NONE') {
copyright += result.WFS_Capabilities['ows:ServiceIdentification']['ows:Fees']['#text'] + ' ';
}
if (BKGWebMap.Util.hasNestedProperty(result, 'wfs:WFS_Capabilities.ows:ServiceIdentification.ows:AccessConstraints.#text') && result['wfs:WFS_Capabilities']['ows:ServiceIdentification']['ows:AccessConstraints']['#text'] !== '' && result['wfs:WFS_Capabilities']['ows:ServiceIdentification']['ows:AccessConstraints']['#text'] !== 'NONE') {
copyright += result['wfs:WFS_Capabilities']['ows:ServiceIdentification']['ows:AccessConstraints']['#text'] + ' ';
} else if (BKGWebMap.Util.hasNestedProperty(result, 'WFS_Capabilities.ows:ServiceIdentification.ows:AccessConstraints.#text') && result.WFS_Capabilities['ows:ServiceIdentification']['ows:AccessConstraints']['#text'] !== '' && result.WFS_Capabilities['ows:ServiceIdentification']['ows:AccessConstraints']['#text'] !== 'NONE') {
copyright += result.WFS_Capabilities['ows:ServiceIdentification']['ows:AccessConstraints']['#text'] + ' ';
}
}
if (copyright) {
config.copyright = copyright;
}
return callback(layer);
}
};
xhr.onerror = function () {
return callback(layer);
};
xhr.send();
},
MARKER: function (createConfig, map, config, styles, bkg, callback) {
var originalConfig = BKGWebMap.Util.deepCopy(config);
delete originalConfig.isBaseLayer;
config.originalConfig = originalConfig;
config.uniqueId = BKGWebMap.Util.uniqueId();
if (!config.id) {
config.id = BKGWebMap.Util.generateLayerId();
}
var i;
var features = [];
var copyright = '';
var edit = BKGWebMap.LAYERS.MARKER.EDIT;
// Copyright
if (config.copyright && typeof config.copyright === 'string' && config.copyright !== '') {
copyright = config.copyright;
}
// Edit
if (typeof config.edit !== 'boolean') {
config.edit = edit;
}
// Style
var styleObject = BKGWebMap.Style.createStyles([BKGWebMap.DEFAULT_STYLE]);
var style = styleObject['bkgwebmap-defaultstyle'];
if (Object.prototype.hasOwnProperty.call(styles, config.style)) {
config.styleName = config.style;
style = styles[config.style];
}
config.style = style;
var mapProjection = map.getView().getProjection().getCode();
var markerProjection = BKGWebMap.LAYERS.MARKER.PROJECTION;
// Source -> Projection (srsName)
if (config.srsName && typeof config.srsName === 'string' && config.srsName !== '') {
markerProjection = config.srsName;
}
// Visible
config.visible = BKGWebMap.LAYERS.MARKER.VISIBLE;
if (typeof config.visibility === 'boolean' && config.visibility === false) {
config.visible = config.visibility;
}
delete config.visibility;
// Source -> Features
if (!config.markers || !(config.markers instanceof Array)) {
window.console.log(BKGWebMap.ERROR.markersMissing);
return callback(undefined);
}
for (i = 0; i < config.markers.length; i++) {
if (config.markers[i] instanceof ol.Feature) {
// In case the user has used directly the class ol.Feature (hidden feature...)
features.push(config.markers[i]);
} else if (config.markers[i].coordinates && config.markers[i].coordinates.lat && typeof config.markers[i].coordinates.lat === 'number' && config.markers[i].coordinates.lon && typeof config.markers[i].coordinates.lon === 'number') {
features.push(new ol.Feature({
geometry: new ol.geom.Point(ol.proj.transform([config.markers[i].coordinates.lon, config.markers[i].coordinates.lat], markerProjection, mapProjection)),
name: config.markers[i].content
}));
}
}
if (features.length === 0) {
window.console.log(BKGWebMap.ERROR.markersMissing);
return callback(undefined);
}
ol.inherits(BKGWebMap.Layer.MARKER, ol.layer.Vector);
var layer = new BKGWebMap.Layer.MARKER(config);
var sourceOptions = {
features: features
};
// All other possible Vector source options, even those not included in Documentation
var extraSourceOptions = [
'attributions',
'logo',
'overlaps',
'useSpatialIndex',
'wrapX'
];
for (i = 0; i < extraSourceOptions.length; i++) {
if (config[extraSourceOptions[i]]) {
sourceOptions[extraSourceOptions[i]] = config[extraSourceOptions[i]];
}
}
var source = new ol.source.Vector(sourceOptions);
layer.setSource(source);
if (copyright) {
config.copyright = copyright;
}
return callback(layer);
},
CSV: function (createConfig, map, config, styles, bkg, callback) {
var originalConfig = BKGWebMap.Util.deepCopy(config);
delete originalConfig.isBaseLayer;
config.originalConfig = originalConfig;
config.uniqueId = BKGWebMap.Util.uniqueId();
if (!config.id) {
config.id = BKGWebMap.Util.generateLayerId();
}
var url = config.url;
var mapProjection = map.getView().getProjection().getCode();
var csvProjection = BKGWebMap.LAYERS.CSV.PROJECTION;
var copyright = '';
var edit = BKGWebMap.LAYERS.CSV.EDIT;
// Copyright
if (config.copyright && typeof config.copyright === 'string' && config.copyright !== '') {
copyright = config.copyright;
}
// Edit
if (typeof config.edit !== 'boolean') {
config.edit = edit;
}
// Style
var styleObject = BKGWebMap.Style.createStyles([BKGWebMap.DEFAULT_STYLE]);
var style = styleObject['bkgwebmap-defaultstyle'];
if (Object.prototype.hasOwnProperty.call(styles, config.style)) {
config.styleName = config.style;
style = styles[config.style];
}
config.style = style;
// Source -> Projection (srsName)
if (config.srsName && typeof config.srsName === 'string' && config.srsName !== '') {
csvProjection = config.srsName;
}
// Options
if (!config.csvOptions || ((typeof config.csvOptions !== 'object' && config.csvOptions.constructor !== Object))) {
window.console.log(BKGWebMap.ERROR.csvExcelOptions + config.type);
return callback(undefined);
}
// Visible
config.visible = BKGWebMap.LAYERS.CSV.VISIBLE;
if (typeof config.visibility === 'boolean' && config.visibility === false) {
config.visible = config.visibility;
}
delete config.visibility;
// Source -> URL
if (typeof url === 'string' && url === '') {
window.console.log(BKGWebMap.ERROR.wrongUrl + config.type);
return callback(undefined);
} else if (url instanceof Array) {
// Used from custom layers control
// createFeaturesFromJson(url);
BKGWebMap.Layer.Util.parseCsvExcelJson('CSV', url, config, config.csvOptions, csvProjection, mapProjection, copyright, callback);
}
// Load csv
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'blob';
var onError = function () {
return callback(undefined);
};
xhr.onerror = onError;
xhr.onload = function () {
if (xhr.status === 200) {
// Encoding
var encoding = BKGWebMap.LAYERS.CSV.ENCODING;
if (config.csvOptions && config.csvOptions.encoding && typeof config.csvOptions.encoding === 'string' && config.csvOptions.encoding !== '') {
encoding = config.csvOptions.encoding;
}
// Delimiter
var delimiter = BKGWebMap.LAYERS.CSV.DELIMITER;
if (config.csvOptions && config.csvOptions.delimiter && typeof config.csvOptions.delimiter === 'string' && config.csvOptions.delimiter !== '') {
delimiter = config.csvOptions.delimiter;
}
var reader = new FileReader();
reader.readAsText(xhr.response, encoding);
reader.onload = function (e) {
var result = 'sep=' + delimiter + '\n' + e.target.result;
var workbook = XLSX.read(result, { type: 'binary' });
var sheet = workbook.Sheets[workbook.SheetNames[0]];
var json = XLSX.utils.sheet_to_json(sheet, { header: 1 });
BKGWebMap.Layer.Util.parseCsvExcelJson('CSV', json, config, config.csvOptions, csvProjection, mapProjection, copyright, callback);
};
} else {
onError();
}
};
if (!(url instanceof Array)) {
xhr.send();
}
},
XLS: function (createConfig, map, config, styles, bkg, callback) {
var originalConfig = BKGWebMap.Util.deepCopy(config);
delete originalConfig.isBaseLayer;
config.originalConfig = originalConfig;
config.uniqueId = BKGWebMap.Util.uniqueId();
if (!config.id) {
config.id = BKGWebMap.Util.generateLayerId();
}
var url = config.url;
var mapProjection = map.getView().getProjection().getCode();
var excelProjection = BKGWebMap.LAYERS.XLS.PROJECTION;
var copyright = '';
var edit = BKGWebMap.LAYERS.XLS.EDIT;
// Copyright
if (config.copyright && typeof config.copyright === 'string' && config.copyright !== '') {
copyright = config.copyright;
}
// Edit
if (typeof config.edit !== 'boolean') {
config.edit = edit;
}
// Style
var styleObject = BKGWebMap.Style.createStyles([BKGWebMap.DEFAULT_STYLE]);
var style = styleObject['bkgwebmap-defaultstyle'];
if (Object.prototype.hasOwnProperty.call(styles, config.style)) {
config.styleName = config.style;
style = styles[config.style];
}
config.style = style;
// Source -> Projection (srsName)
if (config.srsName && typeof config.srsName === 'string' && config.srsName !== '') {
excelProjection = config.srsName;
}
// Options
if (!config.excelOptions || ((typeof config.excelOptions !== 'object' && config.excelOptions.constructor !== Object))) {
window.console.log(BKGWebMap.ERROR.csvExcelOptions + config.type);
return callback(undefined);
}
// Visible
config.visible = BKGWebMap.LAYERS.XLS.VISIBLE;
if (typeof config.visibility === 'boolean' && config.visibility === false) {
config.visible = config.visibility;
}
delete config.visibility;
// Source -> URL
if (typeof url === 'string' && url === '') {
window.console.log(BKGWebMap.ERROR.wrongUrl + config.type);
return callback(undefined);
} else if (url instanceof Array) {
// Used from custom layers control
BKGWebMap.Layer.Util.parseCsvExcelJson('XLS', url, config, config.excelOptions, excelProjection, mapProjection, copyright, callback);
}
// Load excel
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'arraybuffer';
var onError = function () {
return callback(undefined);
};
xhr.onerror = onError;
xhr.onload = function () {
if (xhr.status === 200) {
var response = new Uint8Array(xhr.response);
var workbook = XLSX.read(response, { type: 'array' });
// Get data from first Sheet ONLY
var data = workbook.Sheets[workbook.SheetNames[0]];
var json = XLSX.utils.sheet_to_json(data, { header: 1 });
BKGWebMap.Layer.Util.parseCsvExcelJson('XLS', json, config, config.excelOptions, excelProjection, mapProjection, copyright, callback);
} else {
onError();
}
};
if (!(url instanceof Array)) {
xhr.send();
}
},
GPS: function (createConfig, map, config, styles, bkg, callback) {
var originalConfig = BKGWebMap.Util.deepCopy(config);
delete originalConfig.isBaseLayer;
config.originalConfig = originalConfig;
config.uniqueId = BKGWebMap.Util.uniqueId();
if (!config.id) {
config.id = BKGWebMap.Util.generateLayerId();
}
var url = config.url;
var copyright = '';
var edit = BKGWebMap.LAYERS.GPS.EDIT;
var mapProjection = map.getView().getProjection().getCode();
var gpsProjection = 'EPSG:4326';
// Copyright
if (config.copyright && typeof config.copyright === 'string' && config.copyright !== '') {
copyright = config.copyright;
}
// Edit
if (typeof config.edit !== 'boolean') {
config.edit = edit;
}
// Style
var styleObject = BKGWebMap.Style.createStyles([BKGWebMap.DEFAULT_STYLE]);
var style = styleObject['bkgwebmap-defaultstyle'];
if (Object.prototype.hasOwnProperty.call(styles, config.style)) {
config.styleName = config.style;
style = styles[config.style];
}
config.style = style;
// Visible
config.visible = BKGWebMap.LAYERS.GPS.VISIBLE;
if (typeof config.visibility === 'boolean' && config.visibility === false) {
config.visible = config.visibility;
}
delete config.visibility;
// Source -> URL
if (typeof url === 'string' && url === '') {
window.console.log(BKGWebMap.ERROR.wrongUrl + config.type);
return callback(undefined);
} else if (url instanceof Array) {
// Used from custom layers control
BKGWebMap.Layer.Util.createFeaturesForGps(url[0], config, gpsProjection, mapProjection, callback);
} else {
ol.inherits(BKGWebMap.Layer.GPS, ol.layer.Vector);
var layer = new BKGWebMap.Layer.GPS(config);
var source = new ol.source.Vector({
url: url,
format: new ol.format.GPX()
});
layer.setSource(source);
if (copyright) {
config.copyright = copyright;
}
return callback(layer);
}
},
VECTOR: function (createConfig, map, config, styles, bkg, callback) {
var mapProjection = map.getView().getProjection().getCode();
var copyright = '';
var geojson;
var edit = BKGWebMap.LAYERS.VECTOR.EDIT;
config.uniqueId = BKGWebMap.Util.uniqueId();
if (!config.id) {
config.id = BKGWebMap.Util.generateLayerId();
}
if (!config.features || ((typeof config.features !== 'object' && config.features.constructor !== Object))) {
return callback(undefined);
}
geojson = config.features;
// Copyright
if (config.copyright && typeof config.copyright === 'string' && config.copyright !== '') {
copyright = config.copyright;
}
// Edit
if (typeof config.edit !== 'boolean') {
config.edit = edit;
}
// Style
var styleObject = BKGWebMap.Style.createStyles([BKGWebMap.DEFAULT_STYLE]);
var style = styleObject['bkgwebmap-defaultstyle'];
if (Object.prototype.hasOwnProperty.call(styles, config.style)) {
config.styleName = config.style;
style = styles[config.style];
}
config.style = style;
// Visible
config.visible = BKGWebMap.LAYERS.VECTOR.VISIBLE;
if (typeof config.visibility === 'boolean' && config.visibility === false) {
config.visible = config.visibility;
}
delete config.visibility;
ol.inherits(BKGWebMap.Layer.VECTOR, ol.layer.Vector);
var layer = new BKGWebMap.Layer.VECTOR(config);
if (copyright) {
config.copyright = copyright;
}
var source = new ol.source.Vector();
layer.setSource(source);
var format = new ol.format.GeoJSON();
var features = format.readFeatures(geojson, {
dataProjection: 'EPSG:4326',
featureProjection: mapProjection
});
source.addFeatures(features);
return callback(layer);
},
GROUP: function (createConfig, map, config, styles, bkg, callback) {
var originalConfig = BKGWebMap.Util.deepCopy(config);
delete originalConfig.isBaseLayer;
delete originalConfig.layers;
config.originalConfig = originalConfig;
config.uniqueId = BKGWebMap.Util.uniqueId();
if (!config.id) {
config.id = BKGWebMap.Util.generateLayerId();
}
var layers = [];
var layerListLength = config.layers.length;
var counter = 0;
var layerGroup;
if (config.isBaseLayer === true) {
layerGroup = 'baseLayers';
} else {
layerGroup = 'overlays';
}
// Visible
config.visible = BKGWebMap.LAYERS.GROUP.VISIBLE;
if (typeof config.visibility === 'boolean' && config.visibility === false) {
config.visible = config.visibility;
}
delete config.visibility;
// Layers
if (!config.layers || !(config.layers instanceof Array) || config.layers.length === 0) {
window.console.log(BKGWebMap.ERROR.missingLayersGroup);
return callback(undefined);
}
for (var i = 0; i < layerListLength; i++) {
(function () {
var k = i;
createConfig.createLayer(createConfig, map, config.layers[k], layerGroup, styles, bkg, function (singleLayer) {
counter++;
if (singleLayer !== undefined) {
singleLayer.setProperties({
isBaseLayer: false,
uniqueId: BKGWebMap.Util.uniqueId()
});
}
layers[k] = singleLayer;
// Use layers array only if we have loaded all layers
if (counter === layerListLength) {
// Remove undefined from layers array
for (var j = layers.length - 1; j >= 0; j--) {
if (layers[j] === undefined) {
layers.splice(j, 1);
}
}
layers.reverse();
// Change layers property of config object
config.layers = layers;
ol.inherits(BKGWebMap.Layer.GROUP, ol.layer.Group);
var layer = new BKGWebMap.Layer.GROUP(config);
return callback(layer);
}
});
}());
}
},
BKG: function (createConfig, map, config, styles, bkg, callback) {
var originalConfig = BKGWebMap.Util.deepCopy(config);
delete originalConfig.isBaseLayer;
config.originalConfig = originalConfig;
config.uniqueId = BKGWebMap.Util.uniqueId();
if (!config.id) {
config.id = BKGWebMap.Util.generateLayerId();
}
var projection = map.getView().getProjection().getCode();
var registryUrl = BKGWebMap.SERVICE_REGISTRY;
var ref = config.ref;
var properties = {};
var layerGroup;
if (config.isBaseLayer === true) {
layerGroup = 'baseLayers';
} else {
layerGroup = 'overlays';
}
// Find if we already have CookieCheck control. If not, add it and activate it only if there is no UUID (or appID).
var cookieCheckControl = false;
if (!BKGWebMap.SECURITY.UUID && !BKGWebMap.CONTROLS.tools.cookieCheck.doNotActivate) {
map.getControls().forEach(function (control) {
if (BKGWebMap.Control.CookieCheck && control instanceof BKGWebMap.Control.CookieCheck) {
cookieCheckControl = true;
if (!control.active) {
control.activateCookieTest();
}
}
});
if (!cookieCheckControl) {
var CookieCheckClass = BKGWebMap.Control.FACTORIES.cookieCheck();
var cookieCheck = new CookieCheckClass(map, 'cookieCheck', {}, null);
map.addControl(cookieCheck);
BKGWebMap.Controls.cookieCheck = cookieCheck;
cookieCheck.activateCookieTest();
}
}
// ref
if (typeof ref !== 'string' || ref === '') {
window.console.log(BKGWebMap.ERROR.missingRefInBkg);
return callback(undefined);
}
// Source -> Projection (srsName)
if (config.srsName && typeof config.srsName === 'string' && config.srsName !== '') {
projection = config.srsName;
}
// Properties that overwrite preconfigured values
if (config.properties || ((typeof config.properties === 'object' && config.properties.constructor === Object))) {
properties = config.properties;
}
// Use parameters for GET request
var params = '/' + ref + '?srsname=' + projection;
// Find layer info from registry
var xhr = new XMLHttpRequest();
xhr.open('GET', registryUrl + params);
var onError = function () {
return callback(undefined);
};
xhr.onerror = onError;
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
xhr.onload = function () {
var jsonConfig = null;
if (xhr.status === 200) {
jsonConfig = JSON.parse(xhr.responseText);
// Create URL
// Source -> URL
if (typeof jsonConfig.url !== 'string' || jsonConfig.url === '') {
window.console.log(BKGWebMap.ERROR.wrongUrl + config.type);
return callback(undefined);
}
// Be sure to have only one slash in url
if (jsonConfig.url.slice(0, 1) === '/') {
jsonConfig.url = jsonConfig.url.slice(1);
}
if (BKGWebMap.BASE_URL.slice(BKGWebMap.BASE_URL.length - 1, BKGWebMap.BASE_URL.length) !== '/') {
BKGWebMap.BASE_URL += '/';
}
jsonConfig.url = BKGWebMap.BASE_URL + jsonConfig.url;
// Ovewrite name
if (config.name && typeof config.name === 'string' && config.srsName !== '') {
jsonConfig.name = config.name;
}
// Ovewrite default visibility
if (typeof config.visibility === 'boolean') {
jsonConfig.visibility = config.visibility;
}
// Ovewrite opacity
if (config.opacity && typeof config.opacity === 'number') {
jsonConfig.opacity = config.opacity;
}
// Ovewrite minResolution
if (config.minResolution && typeof config.minResolution === 'number') {
jsonConfig.minResolution = config.minResolution;
}
// Ovewrite maxResolution
if (config.maxResolution && typeof config.maxResolution === 'number') {
jsonConfig.maxResolution = config.maxResolution;
}
// Add legendUrl
if (config.legendUrl && typeof config.legendUrl === 'string' && config.legendUrl !== '') {
jsonConfig.legendUrl = config.legendUrl;
}
// Add copyright
if (config.copyright && typeof config.copyright === 'string' && config.copyright !== '') {
jsonConfig.copyright = config.copyright;
}
// Add user id
if (config.id && typeof config.id === 'string' && config.id !== '') {
jsonConfig.id = config.id;
}
// Use properties that overwrite preconfigured values
jsonConfig = BKGWebMap.Util.extend(jsonConfig, properties);
createConfig.createLayer(createConfig, map, jsonConfig, layerGroup, styles, true, function (singleLayer) {
return callback(singleLayer);
});
} else {
onError();
}
};
xhr.send();
},
NONE: function (createConfig, map, config, styles, bkg, callback) {
var originalConfig = BKGWebMap.Util.deepCopy(config);
delete originalConfig.isBaseLayer;
config.originalConfig = originalConfig;
config.name = BKGWebMap.LAYERS.NONE.NAME;
config.visible = false;
config.uniqueId = BKGWebMap.Util.uniqueId();
if (!config.id) {
config.id = BKGWebMap.Util.generateLayerId();
}
ol.inherits(BKGWebMap.Layer.NONE, ol.layer.Image);
var layer = new BKGWebMap.Layer.NONE(config);
layer.setSource(null);
return callback(layer);
}
};
/**
* Helper functions for layers
* @namespace BKGWebMap.Layer.Util
* @type {object}
*/
BKGWebMap.Layer.Util = BKGWebMap.Layer.Util || {};
/**
* Create features for CSV and XLS layers
* @param {array} json - Data from CSV or XLS
* @param {CSV|XLS} config - CSV/XLS Configuration
* @param {string} type - Layer type (CSV/XLS)
* @param {string} dataProjection - Projection of coordinates in CSV/XLS
* @param {string} mapProjection - Map projection
* @returns {object|undefined}
*/
BKGWebMap.Layer.Util.createFeaturesForCsvExcel = function (json, config, type, dataProjection, mapProjection) {
var features = [];
var i;
// Header
var header = BKGWebMap.LAYERS[type].HEADER;
if (typeof config.header === 'boolean') {
header = config.header;
}
var headerArray = [];
var startPosition = 0;
if (header) {
startPosition = 1;
headerArray = json[0];
} else {
startPosition = 0;
if (config.columnNames && config.columnNames instanceof Array) {
headerArray = config.columnNames;
}
}
// Columns to parse
var columns = null;
var typeOfcolumnsToParse;
if (config.columnsToParse && config.columnsToParse instanceof Array) {
columns = config.columnsToParse;
typeOfcolumnsToParse = typeof columns[0];
}
// Create an array with column positions using header names
if (columns && typeOfcolumnsToParse === 'string' && json[0] instanceof Array) {
var tempColumns = [];
var position;
for (i = 0; i < columns.length; i++) {
position = json[0].indexOf(columns[i]);
if (position !== -1) {
tempColumns.push(position + 1);
}
}
columns = tempColumns;
}
if (!columns && json[0] instanceof Array) {
columns = [];
for (i = 0; i < json[0].length; i++) {
columns.push(i + 1);
}
}
if (config.LatColumn && config.LonColumn && json[0] instanceof Array) {
var latColumn;
var lonColumn;
var lat;
var lon;
if (typeof config.LatColumn === 'string') {
var latPosition = json[0].indexOf(config.LatColumn);
if (latPosition !== -1) {
latColumn = latPosition + 1;
}
var lonPosition = json[0].indexOf(config.LonColumn);
if (lonPosition !== -1) {
lonColumn = lonPosition + 1;
}
} else {
latColumn = config.LatColumn;
lonColumn = config.LonColumn;
}
for (i = startPosition; i < json.length; i++) {
if (!json[i][latColumn - 1] || !json[i][lonColumn - 1]) {
continue;
}
lat = parseFloat(json[i][latColumn - 1].replace(',', '.').replace(' ', ''));
lon = parseFloat(json[i][lonColumn - 1].replace(',', '.').replace(' ', ''));
if (isNaN(lat) || isNaN(lon)) {
continue;
}
var properties = {};
for (var k = 0; k < columns.length; k++) {
var key = '';
var value = '';
if (typeof columns[k] === 'number') {
if (header) {
// Try to use titles from 1st line
if (header && headerArray[columns[k] - 1] !== undefined) {
key = headerArray[columns[k] - 1];
}
} else if (headerArray[k] !== undefined && headerArray[k] !== '') {
// Try to use titles defined by user (columnNames)
key = headerArray[k];
} else {
key = 'key' + k;
}
if (json[i][columns[k] - 1] !== undefined) {
value = json[i][columns[k] - 1];
}
properties[key] = value;
}
}
properties.geometry = new ol.geom.Point(ol.proj.transform([lon, lat], dataProjection, mapProjection));
features.push(new ol.Feature(properties));
}
return features;
}
return undefined;
};
/**
* Parse JSON with CSV/XLS data
* @param {string} format - Layer type (CSV/XLS)
* @param {array} json - Array with CSV/XLS data
* @param {CSV|XLS} config - CSV/XLS Configuration
* @param {object} options - Options used to parse data from XLS/CSV
* @param {string} featureProjection - EPSG Code of data projection in XLS/CSV
* @param {string} mapProjection - EPSG Code of map projection
* @param {string|undefined} copyright - Data copyright
* @param {function} callback - Callback function. It will be called when all information of layer are parsed.
* @returns {function}
*/
BKGWebMap.Layer.Util.parseCsvExcelJson = function (format, json, config, options, featureProjection, mapProjection, copyright, callback) {
var features = BKGWebMap.Layer.Util.createFeaturesForCsvExcel(json, options, config.type, featureProjection, mapProjection);
if (features.length === 0) {
window.console.log(BKGWebMap.ERROR.csvExcelCoordMissing + config.type);
return callback(undefined);
}
ol.inherits(BKGWebMap.Layer[format], ol.layer.Vector);
var layer = new BKGWebMap.Layer[format](config);
var sourceOptions = {
features: features
};
// All other possible Vector source options, even those not included in Documentation
var extraSourceOptions = [
'attributions',
'logo',
'overlaps',
'useSpatialIndex',
'wrapX'
];
for (var i = 0; i < extraSourceOptions.length; i++) {
if (config[extraSourceOptions[i]]) {
sourceOptions[extraSourceOptions[i]] = config[extraSourceOptions[i]];
}
}
var source = new ol.source.Vector(sourceOptions);
layer.setSource(source);
if (copyright) {
config.copyright = copyright;
}
return callback(layer);
};
/**
* Create features for GPS through a custom layer
* @param {object} gpx - GPX data
* @param {GPS} config - GPS Configuration
* @param {string} gpsProjection - EPSG Code of GPX data projection
* @param mapProjection - EPSG Code of map projection
* @param {function} callback - Callback function. It will be called when all information of layer are parsed.
* @returns {function}
*/
BKGWebMap.Layer.Util.createFeaturesForGps = function (gpx, config, gpsProjection, mapProjection, callback) {
ol.inherits(BKGWebMap.Layer.GPS, ol.layer.Vector);
var layer = new BKGWebMap.Layer.GPS(config);
var gpxFormat = new ol.format.GPX();
var source = new ol.source.Vector();
layer.setSource(source);
var features = gpxFormat.readFeatures(gpx, {
dataProjection: gpsProjection,
featureProjection: mapProjection
});
source.addFeatures(features);
return callback(layer);
};
/**
* Find configuration for layers that are programmatically added
* @param {object} layer - Layer added
* @returns {object|string}
*/
BKGWebMap.Layer.Util.programmaticLayerConfig = function (layer) {
var config = {};
var layersArray;
var i;
var urls;
if (layer.getSource() instanceof ol.source.ImageWMS) {
config.type = 'WMS';
config.tiles = false;
config.layers = [];
if (layer.getSource().getParams().LAYERS) {
layersArray = layer.getSource().getParams().LAYERS.split(',');
if (layersArray.length) {
for (i = 0; i < layersArray.length; i++) {
config.layers.push({
layer: layersArray[i]
});
}
} else {
return undefined;
}
} else {
return undefined;
}
if (layer.getProperties().name) {
config.name = layer.getProperties().name;
} else {
config.name = 'WMS Layer';
}
if (layer.getProperties().copyright) {
config.copyright = layer.getProperties().copyright;
}
if (layer.getProperties().legendUrl) {
config.legendUrl = layer.getProperties().legendUrl;
}
if (typeof layer.getSource().getUrl === 'function') {
var url = layer.getSource().getUrl();
if (url) {
config.url = url;
} else {
return undefined;
}
} else {
return undefined;
}
return config;
} else if (layer.getSource() instanceof ol.source.TileWMS) {
config.type = 'WMS';
config.tiles = true;
config.layers = [];
if (layer.getSource().getParams().LAYERS) {
layersArray = layer.getSource().getParams().LAYERS.split(',');
if (layersArray.length) {
for (i = 0; i < layersArray.length; i++) {
config.layers.push({
layer: layersArray[i]
});
}
} else {
return undefined;
}
} else {
return undefined;
}
if (layer.getProperties().name) {
config.name = layer.getProperties().name;
} else {
config.name = 'WMS Layer';
}
if (layer.getProperties().copyright) {
config.copyright = layer.getProperties().copyright;
}
if (layer.getProperties().legendUrl) {
config.legendUrl = layer.getProperties().legendUrl;
}
if (typeof layer.getSource().getUrls === 'function') {
urls = layer.getSource().getUrls();
if (urls.length) {
config.url = urls[0];
} else {
return undefined;
}
} else {
return undefined;
}
return config;
} else if (layer.getSource() instanceof ol.source.WMTS) {
if (typeof layer.getSource().getLayer === 'function') {
var layerToLoad = layer.getSource().getLayer();
if (layerToLoad) {
config.layer = layerToLoad;
} else {
return undefined;
}
} else {
return undefined;
}
if (layer.getProperties().name) {
config.name = layer.getProperties().name;
} else {
config.name = 'WMTS Layer';
}
if (typeof layer.getSource().getUrls === 'function') {
urls = layer.getSource().getUrls();
if (urls.length) {
config.url = urls[0];
} else {
return undefined;
}
} else {
return undefined;
}
if (typeof layer.getSource().getMatrixSet === 'function') {
var matrixSet = layer.getSource().getMatrixSet();
if (matrixSet) {
config.matrixSet = matrixSet;
} else {
return undefined;
}
} else {
return undefined;
}
if (typeof layer.getSource().getTileGrid === 'function') {
var tileGrid = layer.getSource().getTileGrid();
if (tileGrid) {
config.tileGrid = tileGrid;
} else {
return undefined;
}
} else {
return undefined;
}
return config;
} else if (layer instanceof ol.layer.Vector) {
var uniqueId = BKGWebMap.Util.uniqueId();
return uniqueId;
}
};