/**
* A script library to import the javascript / css file on the fly
*
* @author Aby Dahana <abydahana@gmail.com>
* @copyright (c) Aksara Laboratory <https://aksaracms.com>
* @license MIT License
*
* This source file is subject to the MIT license that is bundled with this
* source code in the LICENSE.txt file.
*/
"use strict";
let context,
map,
layerVector,
layerOverlap,
clickedPoint,
measurementVector,
routeWayPoints,
routeLineString,
selected,
selectionBox,
drawingManager,
drawingType,
draggableMarker,
lngLat,
colorscheme,
fill_color,
stroke_color,
stroke_width,
icon_pattern,
icon_scale,
geocoder,
geolocation,
apply_coordinate,
apply_latitude,
apply_longitude,
apply_address,
apply_measurement,
apply_route_from,
apply_route_to,
source_url,
rest_url,
wms_url,
panorama,
clicked,
previousCenter = [],
minZoom = 4,
maxZoom = 20,
features = [],
projection = 'EPSG:4326',
popup = new ol.Overlay.Popup(),
highlight = new ol.interaction.Select(),
highlighted,
tileSource;
const openlayers = (function() {
return {
render: function(_this) {
/**
* Render map
*/
context = _this;
if (context.data('tiles-url') && context.data('tiles-url')) {
let provider = (new URL(context.data('tiles-url'))),
site = provider.hostname.split('.'),
domain = site.slice(0).slice(-(site.length === 4 ? 3 : 2)).join('.');
tileSource = new ol.source.XYZ({
url: context.data('tiles-url'),
attributions: [
'© <a href="https://' + domain + '" target="_blank">' + domain + '</a>',
'© <a href="https://openstreetmap.org">OpenStreetMap</a>'
],
crossOrigin: 'anonymous'
});
} else if (config.default_map_tile) {
let provider = (new URL(config.default_map_tile ?? '')),
site = provider.hostname.split('.'),
domain = site.slice(0).slice(-(site.length === 4 ? 3 : 2)).join('.');
tileSource = new ol.source.XYZ({
url: config.default_map_tile ?? 'https://mt{0-3}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}',
attributions: [
'© <a href="https://' + domain + '" target="_blank">' + domain + '</a>',
'© <a href="https://openstreetmap.org">OpenStreetMap</a>'
],
crossOrigin: 'anonymous'
});
} else {
tileSource = new ol.source.OSM();
}
// Apply coordinate to field with matches attribute
apply_coordinate = context.data('apply-coordinate-to');
// Apply latitude to field with matches attribute
apply_latitude = context.data('apply-latitude-to');
// Apply longitude to field with matches attribute
apply_longitude = context.data('apply-longitude-to');
// Apply address to field witch matches attribute
apply_address = context.data('apply-address-to');
// Apply measurement to field with matches attribute
apply_measurement = context.data('apply-measurement-to');
// Route start from
apply_route_from = context.data('route-from') ?? [];
apply_route_from = (typeof(apply_route_from.lat) !== 'undefined' && typeof(apply_route_from.lng) ? [apply_route_from.lat, apply_route_from.lng] : apply_route_from);
// Route end to
apply_route_to = context.data('route-to') ?? [];
apply_route_to = (typeof(apply_route_to.lat) !== 'undefined' && typeof(apply_route_to.lng) ? [apply_route_to.lng, apply_route_to.lat] : apply_route_to);
// Use source url geospatial data
source_url = context.data('source-url');
// Use rest url (ArcGIS)
rest_url = context.data('rest-url');
// Use wms url
wms_url = context.data('wms-url');
// Add street view
panorama = context.data('panorama');
fill_color = (context.data('fill') ? context.data('fill') : null);
stroke_color = (context.data('stroke') ? context.data('stroke') : null);
stroke_width = (context.data('stroke-width') ? context.data('stroke-width') : null);
icon_pattern = (context.data('icon') ? context.data('icon') : null);
icon_scale = (context.data('icon-scale') ? context.data('icon-scale') : null);
lngLat = (context.data('coordinate') ? context.data('coordinate') : (context.data('map-center') ? context.data('map-center') : []));
lngLat = (lngLat && (typeof lngLat.lng !== 'undefined' && typeof lngLat.lat !== 'undefined' ? [lngLat.lng, lngLat.lat] : (typeof lngLat[0] !== 'undefined' && typeof lngLat[1] !== 'undefined' ? [lngLat[0], lngLat[1]] : [107.0825363, -6.2355892])));
colorscheme = (typeof lngLat.colorscheme !== 'undefined' ? lngLat.colorscheme : '#ff0000');
if (! context.attr('id')) {
context.attr('id', 'maps');
}
// Reset previous rendered map
openlayers.reset();
// Render new map
map = new ol.Map({
renderer: 'webgl',
interactions: ol.interaction.defaults({
mouseWheelZoom: false,
dragPan: true
})
.extend([
new ol.interaction.MouseWheelZoom({
condition: function(e) {
return (0 != context.data('mousewheel') || ol.events.condition.platformModifierKeyOnly(e));
}
})
]),
target: context.attr('id'),
layers: [
new ol.layer.Tile({
source: tileSource
})
],
view: new ol.View({
center: ol.proj.fromLonLat(lngLat),
zoom: (context.data('zoom') ? parseInt(context.data('zoom')) : 12),
minZoom: minZoom,
maxZoom: maxZoom
}),
loadTilesWhileAnimating: false,
loadTilesWhileInteracting: false
});
let resolution = map.getView().getResolution();
// Add zoom control to map
(context.attr('control-fullscreen') ? map.addControl(new ol.control.FullScreen()) : '');
// Add scale line to map
(context.attr('control-scaleline') ? map.addControl(new ol.control.ScaleLine()) : '');
// Add mouse position to map
(context.attr('control-mouseposition') ? map.addControl(new ol.control.MousePosition({
coordinateFormat: ol.coordinate.createStringXY(6),
projection: projection,
prefix: 'Degrees',
undefinedHTML: ' '
})) : '');
// Add zoom extent control to map
(context.attr('control-zoom-extent') ? map.addControl(new ol.control.ZoomToExtent({
extent: map.getView().calculateExtent()
})) : '');
$('.ol-zoom-extent').children('button').html('<i class="mdi mdi-home"></i>');
$('.ol-zoom-extent').on('click', function() {
map.getView().fit(map.getView().calculateExtent(), {
size: map.getSize()
}), map.getView().setResolution(resolution)
});
if (! context.data('drawing-type')) {
map.on('singleclick', function(event) {
if (clicked && context.data('finder-url')) {
return false;
}
// Stop all video and audio player
if (typeof mejs !== 'undefined' && typeof mejs.players !== 'undefined') {
$.each(mejs.players, function(key, val) {
if (typeof val.media.hlsPlayer !== 'undefined') {
val.media.hlsPlayer.stopLoad();
val.media.hlsPlayer.destroy();
val.media.remove();
}
});
}
// Add popup overlay
map.addOverlay(popup);
// Add highlighting interaction
map.addInteraction(highlight);
if (popup) {
// Hide previous popup
popup.hide();
}
if (clickedPoint && clickedPoint.getSource().getFeatures().length) {
// Add point to map
clickedPoint.getSource().getFeatures()[0].setGeometry(new ol.geom.Point(event.coordinate));
} else {
// Add point to map using image
clickedPoint = new ol.layer.VectorImage({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Point(event.coordinate)
})
]
}),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
stroke: new ol.style.Stroke({
color: '#880000',
width: 1
}),
fill: new ol.style.Fill({
color: '#ff0000'
})
})
}),
zIndex: 100,
initial: 'clickedPoint'
});
map.addLayer(clickedPoint);
}
let selected = highlight.getFeatures(),
coordinate = ol.proj.transform(event.coordinate, map.getView().getProjection(), projection),
target = map.forEachFeatureAtPixel(event.pixel, function(point, layer) {
return {
point: point,
layer: layer
};
});
if (typeof target !== 'undefined' && typeof target.point !== 'undefined') {
selected.clear();
selected.push(target.point);
}
// Open the popup to find the features on the clicked point
popup.show(event.coordinate, ('<div class="popup-content"><div class="d-flex justify-content-center"><div class="spinner-border spinner-border-sm" role="status"><span class="visually-hidden sr-only">' + phrase('Loading...') + '</span></div></div></div>'));
if (context.data('finder-url')) {
// Attempt to find dataset using finder URL
xhr = $.ajax({
url: context.data('finder-url'),
method: 'POST',
data: {
objectID: (typeof target !== 'undefined' && typeof target.point !== 'undefined' ? target.point.get('object_id') : 0),
coordinate: coordinate
},
beforeSend: function() {
if (xhr) {
xhr.abort();
}
clicked = true;
$('.popup-content').closest('.ol-popup-content').removeAttr('style');
}
})
.done(function(response) {
clicked = false;
if (typeof response.title !== 'undefined' && response.title) {
$('.ol-popup-title').text(response.title);
}
if (typeof response.content !== 'undefined' && response.content) {
// Content found from response
$('.popup-content, .identification-information').html(response.content);
if (typeof response.width === 'number') {
$('.popup-content').closest('.ol-popup-content').attr('style', 'width: ' + response.width + 'px!important');
}
if ($('[role=videoplayer]').length) {
// Run video player when element's found
reactivate(['videoplayer'])
}
} else {
// No data attribute found, close popup
popup.hide();
}
});
} else if (typeof target !== 'undefined' && typeof target.point !== 'undefined' && typeof target.point.getProperties() !== 'undefined') {
// Load attributes from property instead
let content = '',
num = 0;
$.each(target.point.getProperties(), function(key, val) {
if ('geometry' === key) return;
content += '<div class="row text-sm' + (num ? ' border-top' : '') + '"><div class="col-4 text-muted text-end pr-0">' + key + '</div><div class="col-8 text-break-word">' + val + '</div></div>';
num++;
});
$('.popup-content, .identification-information').html(content);
} else {
// No data attribute found, close popup
popup.hide();
}
/**
* Store clicked coordinat for routing
*/
if (coordinate && $('.route-start').length && ! $('.route-start').val()) {
coordinate[0] = coordinate[0].toFixed(6);
coordinate[1] = coordinate[1].toFixed(6);
// Add route start point
$('.route-start').val(coordinate.reverse().join(), projection);
} else if (coordinate && $('.route-end').length && ! $('.route-end').val()) {
coordinate[0] = coordinate[0].toFixed(6);
coordinate[1] = coordinate[1].toFixed(6);
// Add route end point
$('.route-end').val(coordinate.reverse().join(), projection);
}
});
}
map.getView().on('propertychange', function(event) {
if (typeof geolocation !== 'undefined') {
// Stop tracking to prevent map flicker
geolocation.setTracking(false);
}
});
map.on('pointermove', function(event) {
let pixel = map.getEventPixel(event.originalEvent),
hit = map.hasFeatureAtPixel(pixel);
// Set mouse style
map.getViewport().style.cursor = hit ? 'pointer' : '';
});
map.on('moveend', function(event) {
map.addInteraction(highlight);
let selected = highlight.getFeatures().getArray();
if (context.data('clustering-url') && ! selected.length) {
// Get the clustering features
let coordinate = ol.proj.transform(map.getView().getCenter(), map.getView().getProjection(), projection),
latitude = (typeof coordinate[1] !== 'undefined' ? coordinate[1] : 0),
longitude = (typeof coordinate[0] !== 'undefined' ? coordinate[0] : 0),
distance = 0,
checked = [];
try {
checked = (sessionStorage.getItem('checked_layers') ? JSON.parse(sessionStorage.getItem('checked_layers')) : []);
} catch (e) {}
// Don't apply the clustering if there's any checked layers
if (checked.length) return;
if (previousCenter.length) {
// Get distance from previous center point
let line = new ol.geom.LineString([previousCenter, map.getView().getCenter()]),
distance = Math.round(line.getLength() * event.map.getView().getResolution()) / event.map.getView().getResolution();
}
if (! previousCenter.length || distance > event.map.getView().getResolution()) {
// Attempt to get cluster
$.ajax({
url: context.data('clustering-url'),
method: 'POST',
data: {
lat: latitude,
lng: longitude,
keyword: context.closest('form').find('input[name=keyword]').val(),
marker: checked,
distance: Math.round(distance / event.map.getView().getResolution())
},
beforeSend: function() {
context.closest('form').find('button[type=submit]').find('.mdi').removeClass('mdi-magnify').addClass('mdi-loading mdi-spin');
}
})
.done(function(response) {
if (response) {
openlayers.unzip(response, context.closest('form').find('button[type=submit]').find('.mdi'), null, true);
}
previousCenter = map.getView().getCenter();
})
.fail(function() {
context.closest('form').find('button[type=submit]').find('.mdi').removeClass('mdi-loading mdi-spin').addClass('mdi-magnify');
});
}
}
});
// Set coordinate
(context.data('coordinate') ? openlayers.coordinate((1 == context.data('draggable') ? true : false)) : null);
// Set geocoder
(context.data('geocoder') ? openlayers.geocoder(context) : null);
// Set geolocation
(context.data('geolocation') ? openlayers.geolocation() : null);
// Render GeoJSON
(context.data('geojson') ? openlayers.geojsonString(context.data('geojson'), context.data('drawing-type')) : null);
// Render from source URL
(source_url ? openlayers.source(source_url) : null);
// Render from REST's URL
(rest_url ? openlayers.rest(rest_url) : null);
// Apply WMS from URL
(wms_url ? openlayers.wms(wms_url) : null);
// Render from REST's URL
(panorama ? openlayers.panorama() : null);
// Update map size
map.updateSize();
context.find('div').first().css({
width: map.getSize()[0],
height: map.getSize()[1]
});
},
reset: function() {
/**
* Reset map
*/
if (map) {
if (drawingManager) {
map.removeInteraction(drawingManager);
}
if (highlight) {
map.removeInteraction(highlight);
}
map.getLayers().forEach(function(layer, index) {
if ('draggable' == layer.get('initial')) return;
if (layer.getSource()) {
layer.getSource().clear();
}
});
map.updateSize();
}
if (popup) {
popup.hide();
}
if (typeof geolocation !== 'undefined') {
// Stop tracking to prevent map flicker
geolocation.setTracking(false);
}
},
source: function(source) {
/**
* Source extractor
*/
if (! source) return false;
let extension = source.split('.').pop().toLowerCase();
if ('zip' == extension.replace(/\?.*/, '') || 'kmz' == extension.replace(/\?.*/, '')) {
// The source is ZIP or KMZ format
openlayers.unzip(source);
} else if ('kml' == extension.replace(/\?.*/, '')) {
// The source is KML format
openlayers.keyhole(source);
} else {
// The source is GeoJSON format
openlayers.geojson(source);
}
},
unzip: function(source, spinner, ignore_draggable_marker, ignore_fit) {
/**
* Unzipper
*/
if (typeof source.initial !== 'undefined' && sessionStorage.getItem(source.initial)) {
// Open stored blob
openlayers.geojson(sessionStorage.getItem(source.initial), spinner, ignore_draggable_marker, ignore_fit);
} else if (typeof source.url !== 'undefined') {
/**
* Read the KMZ / ZIP File from the given source parameter
*/
try {
// Read KMZ (zip) data
JSZipUtils.getBinaryContent(source.url, function(err, data) {
if (err || data.byteLength < 10) {
console.log(err);
}
// Unzip archive
JSZip.loadAsync(data).then(function(zip) {
// Read extracted datasource
Object.keys(zip.files).forEach(function(filename) {
if ('geojson' == filename.split('.').pop().toLowerCase() || 'json' == filename.split('.').pop().toLowerCase()) {
// Create blob file from extracted data
zip.files[filename].async('string').then(function(blob) {
// Write blob file
let blobURL = URL.createObjectURL(new Blob([blob], {
type: 'application/json'
}));
openlayers.geojson(blobURL, spinner, ignore_draggable_marker, ignore_fit);
});
} else if ('kml' == filename.split('.').pop().toLowerCase()) {
// Create blob file from extracted data
zip.files[filename].async('string').then(function(blob) {
// Write blob file
let blobURL = URL.createObjectURL(new Blob([blob], {
type: 'application/vnd.google-earth.kml+xml'
}));
openlayers.keyhole(blobURL, spinner, ignore_fit, true);
});
}
});
});
});
} catch (e) {
console.log(e);
}
} else if (source.match(/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g)) {
/**
* The source is an url
*/
try {
// Read kmz (zip) data
JSZipUtils.getBinaryContent(source, function(err, data) {
if (err || data.byteLength < 10) {
// Archive cannot be extracted, show error
console.log(err);
}
// Unzip archive
JSZip.loadAsync(data).then(function(zip) {
// Read extracted datasource
Object.keys(zip.files).forEach(function(filename) {
if ('geojson' == filename.split('.').pop().toLowerCase() || 'json' == filename.split('.').pop().toLowerCase()) {
// Create blob file from extracted data
zip.files[filename].async('string').then(function(blob) {
// Write blob file
let blobURL = URL.createObjectURL(new Blob([blob], {
type: 'application/json'
}));
openlayers.geojson(blobURL, spinner, ignore_draggable_marker, ignore_fit);
});
} else if ('kml' == filename.split('.').pop().toLowerCase()) {
// Create blob file from extracted data
zip.files[filename].async('string').then(function(blob) {
// Write blob file
let blobURL = URL.createObjectURL(new Blob([blob], {
type: 'application/vnd.google-earth.kml+xml'
}));
openlayers.keyhole(blobURL, spinner, ignore_fit, true);
});
}
});
});
});
} catch (e) {
console.log(e);
}
}
},
geojsonString: function(shapes, type) {
/**
* Initialize feature from GeoJSON string
*/
let geojson = new ol.format.GeoJSON(),
sourceVector = new ol.source.Vector({});
if (typeof shapes.features !== 'undefined') {
sourceVector = new ol.source.Vector({
features: geojson.readFeatures(
shapes, {
featureProjection: map.getView().getProjection()
}
)
});
} else if (typeof shapes.geometry !== 'undefined') {
sourceVector = new ol.source.Vector({
features: geojson.readFeatures({
type: 'FeatureCollection',
features: [shapes]
}, {
featureProjection: map.getView().getProjection()
})
});
} else if (! context.data('draggable') && typeof shapes.lat !== 'undefined' && typeof shapes.lng !== 'undefined') {
sourceVector = new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.transform([shapes.lng, shapes.lat], projection, map.getView().getProjection()))
})
]
})
}
layerVector = new ol.layer.VectorImage({
source: sourceVector,
style: function(feature, resolution) {
let pattern = null,
icon_width = 0;
if (icon_pattern || feature.get('icon')) {
// Apply pattern from icon
let canvas = document.createElement('canvas'),
canvasContext = canvas.getContext('2d', { willReadFrequently: true }),
image = new Image();
image.src = (icon_pattern ? icon_pattern : feature.get('icon'));
pattern = canvasContext.createPattern(image, 'repeat');
}
return [new ol.style.Style({
image: new ol.style.Icon({
scale: (icon_scale ? icon_scale : (feature.get('icon-scale') ? feature.get('icon-scale') : (feature.get('icon') ? 0.5 : 1))),
src: (icon_pattern ? icon_pattern : (feature.get('icon') ? feature.get('icon') : config.base_url + 'assets/openlayers/resources/icons/marker.png')),
anchor: [0.5, 1]
}),
stroke: new ol.style.Stroke({
color: (stroke_color ? stroke_color : (feature.get('stroke') ? feature.get('stroke') : hex2rgba('#ff0000', 0))),
width: (stroke_width ? stroke_width : (feature.get('stroke-width') ? feature.get('stroke-width') : 2))
}),
fill: new ol.style.Fill({
color: (pattern ? pattern : hex2rgba((fill_color ? fill_color : (feature.get('fill') ? feature.get('fill') : '#ff0000')), (feature.get('fill-opacity') ? feature.get('fill-opacity') : .35)))
}),
text: new ol.style.Text({
text: feature.get('title'),
font: '14px Arial, sans-serif',
fill: new ol.style.Fill({
color: '#000000'
}),
stroke: new ol.style.Stroke({
color: '#ffffff',
width: 3
})
})
})];
}
});
// Push layer to map
map.addLayer(layerVector);
// Fit map to features
(layerVector.getSource().getFeatures().length ? map.getView().fit(layerVector.getSource().getExtent(), {
size: map.getSize()
}) : null);
if (type && ['polygon', 'linestring', 'point'].includes(type)) {
drawingManager = new ol.interaction.Draw({
type: (type === 'polygon' ? 'Polygon' : (type === 'linestring' ? 'LineString' : 'Point')),
source: layerVector.getSource()
});
drawingType = type;
// Event on drawing end
drawingManager.on('drawend', function(event) {
let drawn = event.feature,
features = layerVector.getSource().getFeatures(),
coordinate = ol.proj.transform(drawn.getGeometry().flatCoordinates, map.getView().getProjection(), projection),
output = features.concat(drawn),
measurement = getMeasurement(output);
$(apply_coordinate).val(geojson.writeFeatures(output, {
featureProjection: map.getView().getProjection()
}));
$(apply_latitude).val((typeof coordinate[1] !== 'undefined' ? parseFloat(coordinate[1]).toFixed(6) : 0));
$(apply_longitude).val((typeof coordinate[0] !== 'undefined' ? parseFloat(coordinate[0]).toFixed(6) : 0));
$(apply_measurement).val((measurement.area > 0 ? measurement.area : measurement.distance));
});
let drag = new ol.interaction.Translate({
layers: [layerVector]
});
let modify = new ol.interaction.Modify({
source: layerVector.getSource()
});
let snap = new ol.interaction.Snap({
source: layerVector.getSource()
});
let select = new ol.interaction.Select({
layers: [layerVector],
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: (stroke_color ? stroke_color : hex2rgba('#00ff00', 0)),
width: (stroke_width ? stroke_width : 2),
opacity: .1
}),
fill: new ol.style.Fill({
color: hex2rgba('#00ff00', .35),
opacity: .1
})
})
});
// Add drawing manager
map.addInteraction(drawingManager);
// Add drag interaction
map.addInteraction(drag);
// Add modify interaction
map.addInteraction(modify);
// Add snap interaction
map.addInteraction(snap);
// Add select interaction
map.addInteraction(select);
drag.on('translatestart', function(event) {
// On drag start
popup.hide();
map.removeOverlay(popup);
});
drag.on('translateend', function(event) {
// On drag end
if (typeof event.coordinate !== 'undefined') {
let coordinate = ol.proj.transform(event.coordinate, map.getView().getProjection(), projection);
$(apply_latitude).val((typeof coordinate[1] !== 'undefined' ? parseFloat(coordinate[1]).toFixed(6) : 0));
$(apply_longitude).val((typeof coordinate[0] !== 'undefined' ? parseFloat(coordinate[0]).toFixed(6) : 0));
}
modify.dispatchEvent({
type: 'modifyend'
});
});
modify.on('modifyend', function(event) {
// On modify finish
if (typeof event.target !== 'undefined' && typeof event.target.features_ !== 'undefined') {
event.features = event.target.features_;
}
if (typeof event.features === 'undefined') {
return false;
}
let measurement = getMeasurement(event.features.getArray()),
coordinate = {lat: 0, lng: 0};
event.features.getArray().forEach(function(layer, index) {
coordinate = ol.proj.transform(layer.getGeometry().flatCoordinates, map.getView().getProjection(), projection);
coordinate = {lat: coordinate[1], lng: coordinate[0]};
});
// Apply response to targetted input
$(apply_coordinate).val(geojson.writeFeatures(event.features.getArray(), {
featureProjection: map.getView().getProjection()
}));
$(apply_latitude).val(parseFloat(coordinate.lat).toFixed(6));
$(apply_longitude).val(parseFloat(coordinate.lng).toFixed(6));
$(apply_measurement).val((measurement.area > 0 ? measurement.area : measurement.distance));
if ('google' == config.openlayers_search_provider) {
/**
* Use Google Maps API as geocoder
*/
require.js('https://maps.googleapis.com/maps/api/js?key=' + config.openlayers_search_key + '&libraries=places&language=' + config.language, function() {
let finder = new google.maps.Geocoder();
finder.geocode({
location: coordinate
}, function(response, status) {
if (status === 'OK') {
$(apply_address).val(response[0].formatted_address).trigger('input');
$('#gcd-input-query, #autocomplete').val(response[0].formatted_address);
} else {
console.log(status);
}
});
})
} else {
/**
* Use Nominatim as geocoder
*/
$.get('https://nominatim.openstreetmap.org/reverse?accept-language=id&format=json&lat=' + coordinate.lat + '&lon=' + coordinate.lng + '&addressdetails=1', function(response) {
$(apply_address).val(response.display_name).trigger('input');
$('#gcd-input-query, #autocomplete').val(response.display_name);
});
}
});
select.on('select', function(event) {
if (event.selected.length) {
map.addOverlay(popup);
popup.show(event.mapBrowserEvent.coordinate, ('<div class="popup-content"><div class="list-group list-group-flush"><a href="javascript:void(0)" class="list-group-item list-group-item-action" onclick="removeFeature()"><i class="mdi mdi-trash-can-outline"></i> ' + phrase('Remove feature') + '</a></div></div>'));
highlighted = event.selected[0];
} else {
popup.hide();
map.removeOverlay(popup);
}
});
}
},
geojson: function(source, spinner, ignore_draggable_marker, ignore_fit, aliases, new_file) {
/**
* Render features from geojson
*/
if (layerOverlap && new_file) {
// Remove previously rendered layer overlap
map.removeLayer(layerOverlap);
} else if (layerVector && ! aliases) {
// Remove previously rendered layer vector
map.removeLayer(layerVector);
}
// Initialize layer, use blob, url or geojson string
let vectorSource = new ol.source.Vector({
url: (typeof source.url !== 'undefined' ? source.url : source),
format: new ol.format.GeoJSON({
extractStyles: true
}),
projection: map.getView().getProjection()
});
layerVector = new ol.layer.VectorImage({
source: vectorSource,
style: function(feature, resolution) {
let pattern = null;
if (feature.get('icon')) {
let canvas = document.createElement('canvas'),
canvasContext = canvas.getContext('2d', { willReadFrequently: true }),
image = new Image();
image.src = feature.get('icon');
pattern = canvasContext.createPattern(image, 'repeat');
}
if (feature.get('selected')) {
selected.push(feature);
}
return [new ol.style.Style({
image: new ol.style.Icon({
scale: (icon_scale ? icon_scale : (feature.get('icon-scale') ? feature.get('icon-scale') : 0.5)),
src: (icon_pattern ? icon_pattern : (feature.get('icon') ? feature.get('icon') : config.base_url + 'assets/openlayers/resources/icons/marker.png')),
anchor: [0.5, 1]
}),
stroke: new ol.style.Stroke({
color: (stroke_color ? stroke_color : (feature.get('stroke') ? feature.get('stroke') : hex2rgba('#ff0000', 0))),
width: (stroke_width ? stroke_width : (feature.get('stroke-width') ? feature.get('stroke-width') : 2))
}),
fill: new ol.style.Fill({
color: (pattern ? pattern : hex2rgba((feature.get('fill') ? feature.get('fill') : '#ff0000'), (feature.get('fill-opacity') ? feature.get('fill-opacity') : .35)))
}),
text: new ol.style.Text({
text: (feature.get('layer_type') && $.inArray(feature.get('layer_type'), ['polygon', 'linestring']) !== -1 ? feature.get('label') : null),
font: '14px Arial, sans-serif',
fill: new ol.style.Fill({
color: '#000000'
}),
stroke: new ol.style.Stroke({
color: '#ffffff',
width: 3
})
})
})];
},
initial: (aliases ? 'layerOverlap' : (typeof source.initial !== 'undefined' ? source.initial : 'layerVector')),
url: (typeof source.url !== 'undefined' ? source.url : context.data('finder-url'))
});
// Push layer to map
map.addLayer(layerVector);
if (spinner) {
spinner.removeClass('mdi-magnify').addClass('mdi-loading mdi-spin')
}
// Fit it map to features
let listener = layerVector.getSource().once('change', function(e) {
if (layerVector.getSource().getState() === 'ready') {
let bounds_selected = ol.extent.createEmpty(),
bounds_all = ol.extent.createEmpty(),
found_selected = false,
found_all = false;
for (let i = 0; i < layerVector.getSource().getFeatures().length; i++) {
if (typeof layerVector.getZIndex() === 'undefined') {
// Add zoom index
layerVector.setZIndex(i + 1)
}
const raster = layerVector.getSource().getFeatures()[i].get('raster');
if (raster) {
/**
* GeoTIFF Raster (experimental)
* Export to EPSG:3857 CRS Projection when EPSG:4326 is failed to load
*/
require.js([config.base_url + 'assets/openlayers/231.ol.js'], function() {
const geoTiffLayer = new ol.layer.WebGLTile({
source: new ol.source.GeoTIFF({
zIndex: parseInt(layerVector.getZIndex(i)) - 1,
sources: [{
url: raster,
nodata: 0
}]
})
});
map.addLayer(geoTiffLayer);
})
}
if (layerVector.getSource().getFeatures()[i].getGeometry()) {
if (layerVector.getSource().getFeatures()[i].get('selected')) {
found_selected = true;
ol.extent.extend(bounds_selected, layerVector.getSource().getFeatures()[i].getGeometry().getExtent());
} else {
found_all = true;
ol.extent.extend(bounds_all, layerVector.getSource().getFeatures()[i].getGeometry().getExtent());
}
}
}
if (! ignore_fit) {
if (found_selected) {
map.getView().fit(bounds_selected, {
size: map.getSize()
});
} else if (found_all && ! ignore_draggable_marker) {
map.getView().fit(bounds_all, {
size: map.getSize()
});
if (draggableMarker) {
draggableMarker.getSource().getFeatures()[0].setGeometry(new ol.geom.Point(map.getView().getCenter()));
}
}
}
// Remove spinner
(spinner ? spinner.removeClass('mdi-loading mdi-spin').addClass('mdi-magnify') : '');
// Unbind listener
ol.Observable.unByKey(listener);
}
});
if (aliases) {
// Assign vector to layer overlap
layerOverlap = layerVector;
}
},
keyhole: function(source, spinner, ignore_fit, extract_style) {
/**
* Render the keyhole (kml) type of source
*/
layerOverlap = new ol.layer.VectorImage({
source: new ol.source.Vector({
projection: ol.proj.get(projection),
url: source,
format: new ol.format.KML({
extractStyles: extract_style === true
})
}),
type: 'xml',
initial: 'layerOverlap'
});
// Push layer to map
map.addLayer(layerOverlap);
if (spinner) {
// Remove spinner
spinner.removeClass('mdi-magnify').addClass('mdi-loading mdi-spin')
}
if (! ignore_fit) {
// Fit map to features
layerOverlap.getSource().once('change', function(e) {
if (layerOverlap.getSource().getState() === 'ready') {
if (layerOverlap.getSource().getExtent().length && $.inArray(Infinity, layerOverlap.getSource().getExtent()) === -1) {
map.getView().fit(layerOverlap.getSource().getExtent(), {
size: map.getSize()
});
}
}
})
}
},
rest: function(source) {
/**
* Render the features from ArcGIS Rest API
*/
let esriJSON = new ol.format.EsriJSON();
let vectorSource = new ol.source.Vector({
loader: function(extent, resolution, projection) {
let srid = projection.getCode().split(/:(?=\d+$)/).pop();
$.ajax({
url: source + '/query',
method: 'POST',
data: {
f: 'json',
returnGeometry: true,
spatialRel: 'esriSpatialRelIntersects',
geometry: '{"xmin":' + extent[0] + ',"ymin":' + extent[1] + ',"xmax":' + extent[2] + ',"ymax":' + extent[3] + ',"spatialReference":{"wkid":' + srid + '}}',
geometryType: 'esriGeometryEnvelope',
outFields: '*',
inSR: srid,
outSR: srid
},
dataType: 'jsonp',
success: function(response, xhr, hehe) {
if (response.error) {
console.log(response.error.message, response.error.details.join("\n"));
} else {
let features = esriJSON.readFeatures(response, {
featureProjection: projection
});
if (features.length > 0) {
vectorSource.addFeatures(features);
}
}
}
})
},
strategy: ol.loadingstrategy.tile(ol.tilegrid.createXYZ({
tileSize: 512
}))
});
layerOverlap = new ol.layer.VectorImage({
source: vectorSource
});
// Push layer to map
map.addLayer(layerOverlap);
// Fit map to features
layerOverlap.getSource().once('change', function(e) {
if (layerOverlap.getSource().getState() === 'ready') {
if (layerOverlap.getSource().getExtent().length && $.inArray(Infinity, layerOverlap.getSource().getExtent()) === -1) {
map.getView().fit(layerOverlap.getSource().getExtent(), {
size: map.getSize()
});
}
}
});
},
wms: function(source) {
/**
* Render the features from ArcGIS Rest API
*/
layerOverlap = new ol.layer.Tile({
source: new ol.source.TileWMS({
url: source,
projection: map.getView().getProjection(),
params: {
LAYERS: 'ne:ne'
},
serverType: 'geoserver',
crossOrigin: 'anonymous',
})
});
// Push layer to map
map.addLayer(layerOverlap);
// Fit map to features
layerOverlap.getSource().once('change', function(e) {
if (layerOverlap.getSource().getState() === 'ready') {
if (layerOverlap.getSource().getExtent().length && $.inArray(Infinity, layerOverlap.getSource().getExtent()) === -1) {
map.getView().fit(layerOverlap.getSource().getExtent(), {
size: map.getSize()
});
}
}
});
map.on('singleclick', function(event) {
popup.show(event.coordinate, ('<div class="popup-content"><div class="d-flex justify-content-center"><div class="spinner-border spinner-border-sm" role="status"><span class="visually-hidden sr-only">' + phrase('Loading...') + '</span></div></div></div>'));
const url = layerOverlap.getSource().getFeatureInfoUrl(
event.coordinate,
map.getView().getResolution(),
map.getView().getProjection(), {
INFO_FORMAT: 'text/html'
}
);
if (url) {
fetch(url)
.then((response) => response.text())
.then((html) => {
$('.popup-content').html(html)
});
} else {
popup.hide();
}
});
},
coordinate: function(draggable) {
/**
* Create editable marker
*/
draggableMarker = new ol.layer.VectorImage({
source: new ol.source.Vector({
features: [
new ol.Feature({
type: 'click',
title: '<label class="d-block font-weight-bold text-muted mb-0">' + phrase('Default Marker') + '</label>',
description: '<p class="mb-0">' + phrase('This can be drag on edit mode') + '</p>',
geometry: new ol.geom.Point(map.getView().getCenter())
})
]
}),
style: new ol.style.Style({
image: new ol.style.Icon({
src: config.base_url + 'assets/openlayers/resources/icons/marker.png',
anchor: [0.5, 1]
})
}),
zIndex: 100,
initial: 'draggable'
});
// Push layer to map
map.addLayer(draggableMarker);
if (draggable) {
let drag = new ol.interaction.Translate({
features: new ol.Collection(draggableMarker.getSource().getFeatures())
});
// Add drag interaction to marker
map.addInteraction(drag);
// Event on marker drag end
drag.on('translateend', function(event) {
// Dragend event
if (typeof geolocation !== 'undefined') {
geolocation.setTracking(false);
}
let coordinate = ol.proj.transform(event.coordinate, map.getView().getProjection(), projection);
coordinate = {lat: coordinate[1], lng: coordinate[0]};
$(apply_latitude).val(parseFloat(coordinate.lat).toFixed(6));
$(apply_longitude).val(parseFloat(coordinate.lng).toFixed(6));
$(apply_coordinate).val(JSON.stringify(coordinate));
if ('google' == config.openlayers_search_provider) {
/**
* Use Google Maps API as geocoder
*/
require.js('https://maps.googleapis.com/maps/api/js?key=' + config.openlayers_search_key + '&libraries=places&language=' + config.language, function() {
let finder = new google.maps.Geocoder();
finder.geocode({
location: coordinate
}, function(response, status) {
if (status === 'OK') {
$(apply_address).val(response[0].formatted_address).trigger('input');
$('#gcd-input-query, #autocomplete').val(response[0].formatted_address);
} else {
console.log(status);
}
});
})
} else {
// Getting the address name
$.get('https://nominatim.openstreetmap.org/reverse?accept-language=id&format=json&lat=' + coordinate.lat + '&lon=' + coordinate.lng + '&addressdetails=1', function(response) {
if (typeof response !== 'undefined') {
// Apply to inputs
$(apply_address).val(response.display_name).trigger('input');
$('#gcd-input-query, #autocomplete').val(response.display_name);
}
});
}
});
}
},
geocoder: function(context) {
/**
* Add geocoder (place search)
*/
geocoder = new Geocoder(
'nominatim', {
provider: ('openlayers' == config.openlayers_search_provider ? 'osm' : config.openlayers_search_provider), // osm, mapquest, photon, pelias, bing, opencage
key: config.openlayers_search_key, // API Key
targetType: 'text-input',
countrycodes: 'id',
placeholder: phrase('Search Place'),
limit: 10,
autoComplete: true,
featureStyle: null
}
);
// Add geocoder into map controls directories
map.addControl(geocoder);
if ('google' == config.openlayers_search_provider) {
/**
* Use Google Maps API as geocoder
*/
require.js('https://maps.googleapis.com/maps/api/js?key=' + config.openlayers_search_key + '&libraries=places&language=' + config.language, function() {
let autocomplete = new google.maps.places.Autocomplete(
(document.getElementById('gcd-input-query')), {
componentRestrictions: {
country: 'id'
},
fields: ['formatted_address', 'geometry', 'name'],
strictBounds: false,
types: ['establishment']
}
);
google.maps.event.addListener(autocomplete, 'place_changed', function() {
let place = autocomplete.getPlace();
if (typeof place.geometry === 'undefined') {
return;
}
if (typeof geolocation !== 'undefined') {
geolocation.setTracking(false);
}
if (! drawingType) {
// Apply to inputs
$(apply_coordinate).val(JSON.stringify({
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng()
}));
}
$(context.data('apply-address-to')).val(place.formatted_address).trigger('change');
map.getView().setCenter(ol.proj.transform([place.geometry.location.lng(), place.geometry.location.lat()], projection, map.getView().getProjection()));
if (draggableMarker) {
draggableMarker.getSource().getFeatures()[0].setGeometry(new ol.geom.Point(ol.proj.transform([place.geometry.location.lng(), place.geometry.location.lat()], projection, map.getView().getProjection())));
map.getView().fit(draggableMarker.getSource().getExtent(), {
size: map.getSize()
});
}
if (context.data('finder-url')) {
xhr = $.ajax({
url: context.data('finder-url'),
method: 'POST',
data: {
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng()
},
beforeSend: function() {
if (xhr) {
xhr.abort();
}
}
})
.done(function(response) {
if (typeof response.url !== 'undefined') {
openlayers.unzip(response, null, true);
}
});
}
});
})
} else {
// Create event when address is chosen
geocoder.on('addresschosen', function(response) {
if (typeof geolocation !== 'undefined') {
geolocation.setTracking(false);
}
let coordinate = ol.proj.transform(response.coordinate, map.getView().getProjection(), projection);
coordinate = {lat: coordinate[1], lng: coordinate[0]};
if (! drawingType) {
// Apply to inputs
$(apply_coordinate).val(JSON.stringify(coordinate));
}
$(context.data('apply-address-to')).val(response.address.details.name).trigger('change');
$('#gcd-input-query').val(response.address.details.name);
map.getView().setCenter(response.coordinate);
if (draggableMarker) {
draggableMarker.getSource().getFeatures()[0].setGeometry(new ol.geom.Point(response.coordinate));
map.getView().fit(draggableMarker.getSource().getExtent(), {
size: map.getSize()
});
}
if (context.data('finder-url')) {
xhr = $.ajax({
url: context.data('finder-url'),
method: 'POST',
data: {
lat: coordinate.lat,
lng: coordinate.lng
},
beforeSend: function() {
if (xhr) {
xhr.abort();
}
}
})
.done(function(response) {
if (typeof response.url !== 'undefined') {
openlayers.unzip(response, null, true);
}
});
}
});
}
},
geolocation: function() {
/**
* Add geolocation (user based location)
*/
if (apply_route_to.length) {
navigator.geolocation.watchPosition(function(tracking) {
// Stop tracking to prevent map flicker
openlayers.route([tracking.coords.longitude, tracking.coords.latitude], apply_route_to, 'driving');
},
function(error) {
if (error.code == error.PERMISSION_DENIED) {
alert(phrase('Please enable location to use the directions feature'));
}
});
}
geolocation = new ol.Geolocation({
projection: map.getView().getProjection(),
tracking: true,
trackingOptions: {
enableHighAccuracy: true,
maximumAge: 2000
}
});
// On device position change
geolocation.on('change', function() {
map.getView().setCenter(geolocation.getPosition());
if (draggableMarker) {
draggableMarker.getSource().getFeatures()[0].setGeometry(new ol.geom.Point(geolocation.getPosition()));
map.getView().fit(draggableMarker.getSource().getExtent(), {
size: map.getSize()
});
if (! drawingType) {
let coordinate = ol.proj.transform(geolocation.getPosition(), map.getView().getProjection(), projection);
coordinate = {lat: coordinate[1], lng: coordinate[0]};
// Apply to inputs
$(apply_coordinate).val(JSON.stringify(coordinate));
}
}
let handleTrack = function(e) {
map.getView().setCenter(geolocation.getPosition());
if (draggableMarker) {
draggableMarker.getSource().getFeatures()[0].setGeometry(new ol.geom.Point(geolocation.getPosition()));
map.getView().fit(draggableMarker.getSource().getExtent(), {
size: map.getSize()
});
if (! drawingType) {
let coordinate = ol.proj.transform(geolocation.getPosition(), map.getView().getProjection(), projection);
coordinate = {lat: coordinate[1], lng: coordinate[0]};
// Apply to inputs
$(apply_coordinate).val(JSON.stringify(coordinate));
}
}
};
let icon = document.createElement('i'),
button = document.createElement('button'),
element = document.createElement('div');
icon.setAttribute('class', 'mdi mdi-crosshairs-gps');
button.setAttribute('title', phrase('Track Me'));
button.setAttribute('type', 'button');
button.appendChild(icon);
button.addEventListener('click', handleTrack, false);
element.setAttribute('class', 'ol-track ol-unselectable ol-control');
element.appendChild(button);
map.addControl(
new ol.control.Control({
element: element
})
);
});
geolocation.on('error', function(error) {
console.log(error.message)
});
},
panorama: function() {
require.css([config.base_url + 'assets/openlayers/ol-street-view/ol-street-view.min.css']);
require.js([
config.base_url + 'assets/interactjs/interact.min.js',
config.base_url + 'assets/openlayers/ol-street-view/ol-street-view.min.js'
], function() {
let streetView = new StreetView({
apiKey: config.openlayers_search_key,
language: StreetView.Language.EN,
transparentButton: false,
radius: 50,
updatePegmanToClosestPanorama: true,
size: StreetView.BtnControlSize.Large,
resizable: false,
sizeToggler: true,
zoomOnInit: 18,
minZoom: 13,
defaultMapSize: StreetView.MapSize.Compact,
autoLoadGoogleMaps: true,
i18n: {
dragToInit: 'Drag and drop me'
}
});
map.addControl(streetView);
streetView.once('loadLib', function() {
let panorama = streetView.showStreetView(map.getView().getCenter());
panorama.setPov({
heading: 52,
pitch: -12,
zoom: 1
});
});
streetView.once('streetViewInit', function() {
// Get the panorama instance
var panorama = streetView.getStreetViewPanorama();
let coordinate = ol.proj.transform(map.getView().getCenter(), map.getView().getProjection(), projection);
// Use global google maps functions to add the icon
var markerPos = new google.maps.LatLng(coordinate[1], coordinate[0]);
new google.maps.Marker({
position: markerPos,
map: panorama,
icon: 'https://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=star|FF0000',
title: 'Star'
});
});
})
},
route: function(start_point, end_point, type) {
/**
* Routing machine
*/
$('.find-route-steps').html('');
if (! start_point || ! end_point) {
alert('Please choose the starting point and destination!');
return;
}
if (! $.isArray(start_point)) {
start_point = start_point.split(',').reverse();
}
if (! $.isArray(end_point)) {
end_point = end_point.split(',').reverse();
}
if (routeWayPoints) {
routeWayPoints.getSource().clear();
}
if (routeLineString) {
routeLineString.getSource().clear();
}
routeWayPoints = new ol.layer.VectorImage({
source: new ol.source.Vector(),
style: new ol.style.Style({
image: new ol.style.Icon({
src: config.base_url + 'assets/openlayers/resources/icons/marker.png',
anchor: [0.5, 1]
})
}),
zIndex: 100
});
routeLineString = new ol.layer.VectorImage({
source: new ol.source.Vector(),
style: new ol.style.Style({
stroke: new ol.style.Stroke({
width: 5,
color: [40, 40, 255, 0.8]
})
}),
zIndex: 100
});
$.ajax({
url: config.base_url + 'maps/direction',
method: 'POST',
data: {
profile: type,
start_point: start_point.join(),
end_point: end_point.join(),
partial: true
},
beforeSend: function() {
popup.hide();
$('.find-route-steps').html('');
$('<div class="d-flex justify-content-center loading-result"><div class="spinner-border" role="status"><span class="visually-hidden sr-only">' + phrase('Loading...') + '</span></div></div>').appendTo('.find-route-steps');
}
})
.done(function(response) {
$('.loading-result').remove();
if (! response) {
$('<div class="alert alert-danger">Request take too long, routing cancelled</div>').appendTo('.find-route-steps');
}
// Push route to map
routeLineString.getSource().addFeature(
new ol.Feature({
type: 'route',
geometry: new ol.format.Polyline().readGeometry(response.geometry, {
dataProjection: projection,
featureProjection: map.getView().getProjection()
})
})
);
$.each(response.steps, function(key, val) {
$(
'<div class="py-1' + (key ? ' border-top' : '') + '">' +
'<div class="row align-items-center">' +
'<div class="col-1 col-md-1">' +
'<span class="routing-icon ' + val.icon + '"></span>' +
'</div>' +
'<div class="col-8 col-md-8">' +
val.maneuver +
'</div>' +
'<div class="col-3 col-md-3 text-end">' +
val.distance +
'</div>' +
'</div>' +
'</div>'
)
.appendTo('.find-route-steps');
if ((key + 1) >= response.steps.length && typeof mCustomScrollbar !== 'undefined') {
if ($('.find-route-results.mCustomScrollbar').length) {
$('.find-route-results').mCustomScrollbar('update');
} else {
$('.find-route-results').mCustomScrollbar({
autoHideScrollbar: true,
axis: 'y',
scrollInertia: 170,
mouseWheelPixels: 170,
setHeight: $(window).outerHeight(true) - (($('.navbar').length ? $('.navbar').outerHeight(true) : 0) + ($('.filter-header').length ? $('.filter-header').outerHeight(true) : 0)),
advanced: {
updateOnContentResize: true
}
});
}
}
});
});
// Add point between route to map
routeWayPoints.getSource().addFeature(
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat(start_point))
})
);
routeWayPoints.getSource().addFeature(
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat(end_point))
})
);
// Push route and waypoints to map
map.addLayer(routeLineString);
map.addLayer(routeWayPoints);
// Fit route to extent
(routeWayPoints.getSource().getFeatures().length ? map.getView().fit(routeWayPoints.getSource().getExtent(), {
size: map.getSize()
}) : null);
},
selection: function(appendTo) {
/**
* Selection
*/
map.addInteraction(highlight);
selected = highlight.getFeatures();
selectionBox = new ol.interaction.DragBox({
condition: ol.events.condition.platformModifierKeyOnly
});
map.addInteraction(selectionBox);
selectionBox.on('boxend', function(e) {
let extent = selectionBox.getGeometry().getExtent(),
resolution = map.getView().getResolution(),
exists = [];
map.getLayers().getArray().forEach(function(layer, index) {
if (! index) return;
layer.getSource().forEachFeatureIntersectingExtent(extent, function(feature) {
if (! feature.get('object_id')) {
return;
}
if (! $('#selection-feature-' + feature.get('group_id')).length) {
$('<div id="selection-feature-' + feature.get('group_id') + '" class="mb-3"><h6>' + feature.get('title') + '</h6><div class="row align-items-center"><div class="col-10">' + feature.get('label') + '</div><div class="col-2 text-right text-end"><span class="badge badge-info bg-info" data-group="' + feature.get('group_id') + '">1</span></div></div></div>').appendTo('.selection-information');
} else if ($('span[data-group=' + feature.get('group_id') + ']').length) {
$('span[data-group=' + feature.get('group_id') + ']').text(parseFloat($('span[data-group=' + feature.get('group_id') + ']').text()) + 1);
}
selected.push(feature);
});
});
map.getView().fit(extent, {
size: map.getSize()
});
map.getView().setResolution(resolution);
});
selectionBox.on('boxstart', function(e) {
selected.clear();
});
map.on('click', function() {
selected.clear();
});
},
identification: function(appendTo) {
/**
* Identification
*/
map.addInteraction(highlight);
selected = highlight.getFeatures();
selectionBox = new ol.interaction.DragBox({
condition: ol.events.condition.platformModifierKeyOnly
});
map.addInteraction(selectionBox);
selectionBox.on('boxend', function(e) {
let info = [],
extent = selectionBox.getGeometry().getExtent(),
resolution = map.getView().getResolution(),
exist = [],
num = 0;
$(appendTo).html('');
map.getLayers().getArray().forEach(function(layer, index) {
if (! index) return;
layer.getSource().forEachFeatureIntersectingExtent(extent, function(feature) {
if (! feature.get('object_id')) {
return;
}
let object_id;
if (typeof feature.get('object_id') !== 'undefined') {
object_id = feature.get('object_id');
} else {
// Get primary id from description that contain object_id attribute
object_id = feature.get('description').toLowerCase() + ' ';
object_id = object_id.replace(/(<b[^>]+?>|<b>|<\/b>)/ig, ' ');
object_id = object_id.replace(/\s\s+/g, ' ');
object_id = object_id.substring(object_id.lastIndexOf('object_id = ') + 11);
object_id = object_id.substr(0, object_id.indexOf(' '));
}
feature.setId(object_id);
selected.push(feature);
if ($.inArray(object_id, exist) === -1) {
exist.push(object_id);
$('<div class="identification-item pt-2 pb-2' + ($('.identification-information').children().length > 0 ? ' border-top' : '') + '" data-title="' + feature.get('title') + '" data-url="' + layer.get('url') + '" data-target="' + object_id + '" style="cursor:pointer">' + (feature.get('label') ? feature.get('label') : feature.get('title')) + '</div>').appendTo(appendTo);
}
});
$('body').off('mouseover.identification-item');
$('body').on('mouseover.identification-item', '.identification-item', function(e) {
if (layer.getSource().getFeatureById($(this).data('target'))) {
map.getView().setCenter(ol.extent.getCenter(layer.getSource().getFeatureById($(this).data('target')).getGeometry().getExtent()), {
size: map.getSize()
});
}
});
$('body').off('mouseout.identification-item');
$('body').on('mouseout.identification-item', '.identification-item', function(e) {
popup.hide();
});
$('body').off('click.identification-item touch.identification-item');
$('body').on('click.identification-item touch.identification-item', '.identification-item', function(e) {
if (layer.getSource().getFeatureById($(this).data('target'))) {
map.getView().setCenter(ol.extent.getCenter(layer.getSource().getFeatureById($(this).data('target')).getGeometry().getExtent()), {
size: map.getSize()
});
popup.show(ol.extent.getCenter(layer.getSource().getFeatureById($(this).data('target')).getGeometry().getExtent()), ('<div class="popup-content"></div>'));
xhr = $.ajax({
url: context.data('finder-url'),
method: 'POST',
data: {
objectID: $(this).data('target')
},
beforeSend: function() {
if (xhr) {
xhr.abort();
}
$('.popup-content').html('<div class="d-flex justify-content-center"><div class="spinner-border spinner-border-sm" role="status"><span class="visually-hidden sr-only">' + phrase('Loading...') + '</span></div></div>')
}
})
.done(function(response) {
$('.popup-title').html(response.title);
$('.popup-content').html(response.content);
});
}
})
});
map.getView().fit(extent, {
size: map.getSize()
});
});
selectionBox.on('boxstart', function(e) {
selected.clear();
});
map.on('click', function() {
$(appendTo).html('');
selected.clear();
});
},
measurement: function(type, appendTo) {
/**
* Measurement
*/
$(appendTo).html('');
if (typeof map !== 'undefined' && typeof drawingManager !== 'undefined') {
map.removeInteraction(drawingManager);
drawingManager = null;
}
if (measurementVector) {
measurementVector.getSource().clear();
}
if (type === 'area' || type === 'distance') {
measurementVector = new ol.layer.VectorImage({
source: new ol.source.Vector(),
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: colorscheme,
width: 3
}),
fill: new ol.style.Fill({
color: hex2rgba(colorscheme ?? '#ff0000', .15)
})
})
});
drawingManager = new ol.interaction.Draw({
type: ('area' == type ? 'Polygon' : 'LineString'),
source: measurementVector.getSource()
});
// Push layer to map
map.addLayer(measurementVector);
// Create drawing tools
map.addInteraction(drawingManager);
// Event on drawing end
drawingManager.on('drawstart', function(event) {
clicked = true;
measurementVector.getSource().clear();
});
// Event on drawing end
drawingManager.on('drawend', function(event) {
clicked = false;
let key = (features.length ? parseInt(features.length + 1) : 0),
prepare = [];
features[key] = event.feature.getGeometry().getCoordinates();
$.each(features, function(_key, _val) {
if (! _val) return;
_val = ('area' == type ? _val[0] : _val);
let coord = [];
$.each(_val, function(__key, __val) {
coord.push(ol.proj.transform(__val, map.getView().getProjection(), projection));
});
prepare.push({
type: 'Feature',
geometry: {
type: ('area' == type ? 'Polygon' : 'LineString'),
coordinates: ('area' == type ? [coord] : coord)
},
properties: {}
});
});
let meter = (Math.round('area' == type ? event.feature.getGeometry().getArea() : event.feature.getGeometry().getLength())),
value = $(appendTo).prev('.form-group').find('select').val(),
label = $(appendTo).prev('.form-group').find('select option:selected').html(),
result = ('area' == type ? ('ac' == value ? meter / 4047 : ('mi' == value ? meter / 2.59e+6 : ('ha' == value ? meter / 10000 : ('yd' == value ? meter / 1.196 : ('ft' == value ? meter / 10.764 : ('km' == value ? meter / 1000 : meter)))))) : ('mi' == value ? meter / 1609 : ('yd' == value ? meter / 1.094 : ('ft' == value ? meter / 10.764 : ('km' == value ? meter / 1000 : meter)))));
$(appendTo).html(
'<div class="text-center mt-3">' +
'<h6>' +
phrase('Measurement result') +
'</h6>' +
'<h3>' +
result.toLocaleString('en') +
'</h3>' +
'<h3>' +
label +
'</h3>' +
'</div>'
);
});
} else {
map.on('singleclick', function(event) {
let coordinate = ol.proj.transform(event.coordinate, map.getView().getProjection(), projection),
hdms = ol.coordinate.toStringHDMS(coordinate, 4);
if (measurementVector) {
measurementVector.getSource().clear();
}
measurementVector = new ol.layer.VectorImage({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([coordinate[0], coordinate[1]]))
})
]
}),
style: new ol.style.Style({
image: new ol.style.Icon({
src: config.base_url + 'assets/openlayers/resources/icons/marker.png',
anchor: [0.5, 1]
})
})
});
// Push layer to map
map.addLayer(measurementVector);
$(appendTo).html(
'<div class="text-center mt-3">' +
'<h6 class="mb-3">' +
phrase('Measurement result') +
'</h6>' +
'<div class="row">' +
'<div class="col-6 font-weight-bold">' +
phrase('Latitude') +
'</div>' +
'<div class="col-6 font-weight-bold">' +
phrase('Longitude') +
'</div>' +
'</div>' +
'<div class="row form-group">' +
'<div class="col-6">' +
coordinate[1].toFixed(6) +
'</div>' +
'<div class="col-6">' +
coordinate[0].toFixed(6) +
'</div>' +
'</div>' +
'<div class="form-group">' +
'<label class="d-block font-weight-bold">HDMS</label>' +
'<p>' +
hdms +
'</p>' +
'</div>' +
'</div>'
);
});
}
},
upload: function(data) {
/**
* Upload
*/
if ('zip' !== data.name.split('.').pop().toLowerCase() && 'kmz' !== data.name.split('.').pop().toLowerCase()) {
alert('Only KMZ or ZIP file are allowed to upload!');
return;
}
if (map && layerOverlap) {
map.removeLayer(layerOverlap);
}
try {
// Unzip archive
JSZip.loadAsync(data).then(function(zip) {
let new_file = true;
// Read extracted datasource
Object.keys(zip.files).forEach(function(filename) {
if ('geojson' == filename.split('.').pop().toLowerCase() || 'json' == filename.split('.').pop().toLowerCase()) {
// Create blob file from extracted data
zip.files[filename].async('string').then(function(blob) {
// Write blob file
let blobURL = URL.createObjectURL(new Blob([blob], {
type: 'application/json'
}));
openlayers.geojson(blobURL, null, false, false, true, new_file);
new_file = false;
});
} else if ('kml' == filename.split('.').pop().toLowerCase()) {
// Create blob file from extracted data
zip.files[filename].async('string').then(function(blob) {
// Write blob file
let blobURL = URL.createObjectURL(new Blob([blob], {
type: 'application/vnd.google-earth.kml+xml'
}));
openlayers.keyhole(blobURL, null, false, true);
});
}
});
});
} catch (e) {;
alert('Unsupported geospatial format!')
}
},
download: function(type, pageFormat, dpi) {
/**
* Download
*/
if ('png' == type) {
let canvas = $('.ol-layer canvas');
if (canvas && typeof canvas[0] !== 'undefined') {
if (navigator.msSaveBlob) {
navigator.msSaveBlob(canvas[0].msToBlob(), 'map.png');
} else {
let link = document.getElementById('image-download');
link.href = canvas[0].toDataURL();
link.click();
}
}
} else if ('pdf' == type) {
let canvas = $('.ol-layer canvas'),
center_coordinate = ol.proj.transform(map.getView().getCenter(), map.getView().getProjection(), projection);
if (canvas && typeof canvas[0] !== 'undefined') {
require.js([
config.base_url + 'assets/jspdf/jspdf.min.js',
config.base_url + 'assets/html2canvas/html2canvas.min.js'
], function() {
let unit = map.getView().getProjection().getUnits(),
resolution = map.getView().getResolution(),
format = ($.inArray(pageFormat, ['a0', 'a1', 'a2', 'a3', 'a4', 'a5']) !== -1 ? pageFormat : 'a4'),
doc = new jsPDF({
orientation: 'lanscape',
unit: 'px',
format: format,
userUnit: dpi
});
doc.html($('<div style="position:relative;width:' + doc.internal.pageSize.getWidth() + 'px; height:' + doc.internal.pageSize.getHeight() + 'px;margin:0;padding:15px"><div style="text-align:center;font-weight:bold" style="margin:0;padding:0">' + config.app_name + '</div><div style="border:1px solid black; width:' + (doc.internal.pageSize.getWidth() - 30) + 'px; height:' + (doc.internal.pageSize.getHeight() - 80) + 'px"><img src="' + canvas[0].toDataURL() + '" width="' + (doc.internal.pageSize.getWidth() - 32) + '" height="' + (doc.internal.pageSize.getHeight() - 82) + '" /></div><table width="100%"><tbody><tr><td width="40%"><small style="position:absolute;bottom:15px;font-size:10px">' + phrase('Central') + ': ' + center_coordinate[1].toFixed(4) + ',' + center_coordinate[0].toFixed(4) + '</small></td><td width="40%"><small style="position:absolute;bottom:15px;font-size:10px">' + phrase('Scale') + ' ] 1:' + Math.floor(resolution * ol.proj.Units.METERS_PER_UNIT[unit] * dpi) + unit + ' [</small></td><td width="20%" align="right"><img src="' + config.app_logo + '" style="height:12px;position:absolute;right:15px;bottom:15px" /></td></tr></table></div>').get(0), {
x: 0,
y: 0,
callback: function(doc) {
doc.save('map.pdf');
}
});
});
}
}
}
}
})();
function getMeasurement(features) {
let area = 0,
distance = 0;
features.forEach(function(feature) {
let geometry = feature.getGeometry();
if (geometry instanceof ol.geom.Polygon) {
area += (Math.round(geometry.getArea() * 100) / 100);
distance += (Math.round((new ol.geom.LineString(geometry.getLinearRing(0).getCoordinates())).getLength() * 100) / 100);
} else if (geometry instanceof ol.geom.LineString) {
distance += (Math.round(geometry.getLength() * 100) / 100);
}
});
return {
area: area.toFixed(2),
distance: distance.toFixed(2)
};
}
function removeFeature() {
layerVector.getSource().removeFeature(highlighted);
let geojson = new ol.format.GeoJSON(),
measurement = getMeasurement(layerVector.getSource().getFeatures());
$(apply_coordinate).val(geojson.writeFeatures(layerVector.getSource().getFeatures(), {
featureProjection: map.getView().getProjection()
}));
$(apply_measurement).val((measurement.area > 0 ? measurement.area : measurement.distance));
popup.hide();
map.removeOverlay(popup);
}
|