/*global L, VuFind */ /*exported loadMapSelection */ //Coordinate order: Storage and Query: WENS ; Display: WSEN function loadMapSelection(geoField, boundingBox, baseURL, homeURL, searchParams, resultsCoords, basemap) { // Initialize variables var searchboxLayer = L.featureGroup(); var drawnItemsLayer = L.featureGroup(); var mcgIDs = []; var clickedIDs = []; var clickedBounds = []; var drawnItems; var basemapLayer = new L.TileLayer(basemap[0], {attribution: basemap[1]}); var mapSearch; // Define styles for icons and clusters var searchIcon = L.Icon.extend({ options: { iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] } }); // Red will be used for search results display var redIcon = new searchIcon({ iconUrl: VuFind.path + '/themes/bootstrap3/css/vendor/leaflet/images/marker-icon-2x-red.png', shadowUrl: VuFind.path + '/themes/bootstrap3/css/vendor/leaflet/images/marker-shadow.png' }); var redRectIcon = new searchIcon({ iconUrl: VuFind.path + '/themes/bootstrap3/css/vendor/leaflet/images/rectangle-icon-2x-red.png', shadowUrl: VuFind.path + '/themes/bootstrap3/css/vendor/leaflet/images/marker-shadow.png' }); // Blue will be used when a user selects a geofeature var blueIcon = new searchIcon({ iconUrl: VuFind.path + '/themes/bootstrap3/css/vendor/leaflet/images/marker-icon-2x-blue.png', shadowUrl: VuFind.path + '/themes/bootstrap3/css/vendor/leaflet/images/marker-shadow.png' }); var blueRectIcon = new searchIcon({ iconUrl: VuFind.path + '/themes/bootstrap3/css/vendor/leaflet/images/rectangle-icon-2x-blue.png', shadowUrl: VuFind.path + '/themes/bootstrap3/css/vendor/leaflet/images/marker-shadow.png' }); // Initialize marker clusters with icon colors var markerClusters = new L.MarkerClusterGroup({ iconCreateFunction: function icf(cluster) { var childCount = cluster.getChildCount(); var markers = cluster.getAllChildMarkers(); var cstatus = ""; for (var i = 0; i < markers.length; i++) { cstatus = markers[i].options.recStatus; i = i + markers[i].options.total; } var c = ' marker-cluster-'; if (cstatus === 'active') { c += 'active'; } else { c += 'inactive'; } return new L.DivIcon({ html: '
' + childCount + '
', className: 'marker-cluster' + c, iconSize: new L.Point(40, 40) }); } }); // Handle user interaction with markers and rectangles //----------------------------------------------------// function onClick() { mapSearch.eachLayer(function msl(layer) { if (layer.options.id === "mRect") { mapSearch.removeLayer(layer); } }); // Reset previously selected features to inactive color - RED if (clickedIDs.length > 0) { markerClusters.eachLayer(function mcl(layer){ if (layer.options.recID === clickedIDs[0]) { layer.options.recStatus = 'inactive'; layer._popup.setContent(layer.options.recPopup); if (layer.options.recType === "rectangle") { layer.setIcon(redRectIcon); } else { layer.setIcon(redIcon); } } }); clickedIDs = []; clickedBounds = []; } //Handle current feature selection //Change color of all features with thisID to BLUE var thisID = this.options.recID; clickedIDs.push(thisID); var j = 0; markerClusters.eachLayer(function mc(layer){ if (layer.options.recID === thisID) { j = j++; layer.options.recStatus = 'active'; if (layer.options.recType === "rectangle") { layer.setIcon(blueRectIcon); } else { layer.setIcon(blueIcon); } clickedBounds.push([layer.getLatLng().lat, layer.getLatLng().lng]); if (layer.options.recType === "rectangle") { // create rectangle from options and show var mRect_sw = L.latLng([layer.options.recS, layer.options.recW]); var mRect_ne = L.latLng([layer.options.recN, layer.options.recE]); var mRect = L.rectangle([[mRect_sw, mRect_ne]], { color: '#3388ff', fillOcpacity: 0.1, weight: 2, id: 'mRect' }); mRect.bindPopup(L.popup().setContent(layer.options.rmPopup)); var mrBounds = mRect.getBounds(); clickedBounds.push([ [mrBounds.getSouthWest().lat, mrBounds.getSouthWest().lng], [mrBounds.getNorthEast().lat, mrBounds.getNorthEast().lng] ]); mapSearch.addLayer(mRect); } } }); markerClusters.refreshClusters(); // Check if there are multiple markers at this location // If so, update popup to show title for all rectangles by // combining popup content. thisID = this.options.recID; var thisLat = this.getLatLng().lat; var thisLng = this.getLatLng().lng; var updatePopup = [this._popup.getContent()]; markerClusters.eachLayer(function mc(layer){ var mLat = layer.getLatLng().lat; var mLng = layer.getLatLng().lng; var mPopup = layer._popup.getContent(); if ((mLat === thisLat && mLng === thisLng) && updatePopup.indexOf(mPopup) < 0) { updatePopup.push(mPopup); } }); this._popup.setContent(updatePopup.join(" ")); } // Searchbox //-------------------------------------// // Retrieve searchbox coordinates var sb_west = boundingBox[0]; var sb_south = boundingBox[1]; var sb_east = boundingBox[2]; var sb_north = boundingBox[3]; // Adjust searchbox to a 0-360 grid if it crosses the dateline if (sb_west > sb_east) { // Move west left of east if (sb_east >= 0) { sb_west = sb_west - 360; } else { // Move east right of west sb_east = sb_east + 360; } } var sb_sw = L.latLng([sb_south, sb_west]); var sb_ne = L.latLng([sb_north, sb_east]); // Create searchBox feature var searchboxFeature = L.rectangle ([[sb_sw, sb_ne]], { color: 'red', fillColor: 'red', fillOcpacity: 0.4, weight: 2 }); var sb_bounds = searchboxFeature.getBounds(); var sb_center = sb_bounds.getCenter(); searchboxFeature.addTo(searchboxLayer); // Search results //-------------------------------------// // Create a new vector type for rectangle features // with getLatLng and setLatLng methods. L.RectangleClusterable = L.Rectangle.extend({ _originalInitialize: L.Rectangle.prototype.initialize, initialize: function lrc(bounds, options) { this._originalInitialize(bounds, options); this._latlng = this.getBounds().getCenter(); }, getLatLng: function e() { return this._latlng; }, setLatLng: function e() {} }); // Process result coordinates for (var i = 0; i < resultsCoords.length; ++i ) { var rcType; var rcFeature; var rcStatus = "inactive"; var recID = resultsCoords[i][0]; var recTitle = resultsCoords[i][1]; var popupContent = '
' + recTitle + '
'; var popup = L.popup().setContent(popupContent); var rc_west = resultsCoords[i][2]; var rc_east = resultsCoords[i][3]; var rc_north = resultsCoords[i][4]; var rc_south = resultsCoords[i][5]; sb_west = searchboxFeature.getBounds().getWest(); sb_east = searchboxFeature.getBounds().getEast(); if (sb_west >= -180 && sb_east <= 180) { // do nothing } else { //move coordinates if they are outside of searchbox bounds if (rc_west < sb_west ) { rc_west = rc_west + 360; rc_east = rc_east + 360; } if (rc_east > sb_east) { rc_west = rc_west - 360; rc_east = rc_east - 360; } } if (rc_west === rc_east && rc_north === rc_south) { rcType = "point"; rcFeature = L.marker([rc_south, rc_west], { recID: recID, recType: rcType, recStatus: rcStatus, recPopup: popupContent, icon: redIcon }); } else { rcType = "rectangle"; rcFeature = new L.RectangleClusterable([ [rc_south, rc_west], [rc_north, rc_east] ], {recID: recID, recType: rcType, recStatus: rcStatus, recPopup: popupContent, color: '#910a0a' }); } rcFeature.bindPopup(popup); rcFeature.on('click', onClick); // Only add feature to markerClusters if it is within or intersects searchbox if (rcType === "rectangle") { if (searchboxFeature.getBounds().intersects(rcFeature.getBounds())) { // add center point to layer var rectCtr = rcFeature.getBounds().getCenter(); var rmPopupContent = '
' + recTitle + '
' + VuFind.translate('rectangle_center_message') + '
'; var rmPopup = L.popup().setContent(rmPopupContent); var rectMarker = L.marker(rectCtr, { recID: recID, recType: "rectangle", recStatus: rcStatus, recPopup: rmPopupContent, rmPopup: popupContent, recN: rc_north, recS: rc_south, recE: rc_east, recW: rc_west, icon: redRectIcon }); rectMarker.bindPopup(rmPopup); rectMarker.on('click', onClick); markerClusters.addLayer(rectMarker); mcgIDs.push(recID); } } else if (searchboxFeature.getBounds().contains(rcFeature.getLatLng())){ markerClusters.addLayer(rcFeature); mcgIDs.push(recID); } } // Turn on map selection pane $('#geo_search').show(); // Create map mapSearch = new L.Map ("geo_search_map", { layers: [basemapLayer, searchboxLayer, markerClusters, drawnItemsLayer], center: sb_center }); mapSearch.fitBounds(sb_bounds); // Add search functionality drawnItems = new L.Draw.Rectangle(mapSearch); mapSearch.on('draw:created', function ms(e) { var layer = e.layer; drawnItemsLayer.addLayer(layer); // Get search box coordinates SW, NW, NE, SE // note the wrap() function creates 180 to -180 compliant longitude values. var di_ne = layer.getBounds().getNorthEast().wrap(); var di_sw = layer.getBounds().getSouthWest().wrap(); var di_north = di_ne.lat; var di_east = di_ne.lng; var di_south = di_sw.lat; var di_west = di_sw.lng; //Create search query var rawFilter = geoField + ':Intersects(ENVELOPE(' + di_west + ', ' + di_east + ', ' + di_north + ', ' + di_south + '))'; location.href = baseURL + searchParams + "&filter[]=" + rawFilter; }, this); document.getElementById("draw_box").onclick = function drawSearchBox() { drawnItemsLayer.clearLayers(); new L.Draw.Rectangle(mapSearch, drawnItems.options.rectangle).enable(); }; // If user clicks on map anywhere turn all features to inactive color - RED // and reset clicked arrays mapSearch.on('click', function ms() { mapSearch.eachLayer(function msl(layer) { if (layer.options.id === "mRect") { mapSearch.removeLayer(layer); } }); if (clickedIDs.length > 0) { markerClusters.eachLayer(function mc(layer){ layer.options.recStatus = 'inactive'; if (layer.options.recType === "rectangle") { layer.setIcon(redRectIcon); } else { layer.setIcon(redIcon); } }); clickedIDs = []; clickedBounds = []; markerClusters.refreshClusters(); } }); }