PHP Classes

File: public/assets/local/js/openlayers.min.js

Recommend this page to a friend!
  Classes of Aby Dahana   Aksara   public/assets/local/js/openlayers.min.js   Download  
File: public/assets/local/js/openlayers.min.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Aksara
A CodeIgniter based API and CRUD generator
Author: By
Last change: Refine and fix core js file
Date: 4 days ago
Size: 95,801 bytes
 

Contents

Class file image Download
/** * 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: '&nbsp;' })) : ''); // 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); }