@@ -49,6 +49,8 @@ const lmeState = {
azureMapsKey : null ,
azureAttribution : null ,
managerHighlight : null ,
managerHighlightedObjectId : null ,
managerHighlightedCategoryKey : null ,
managerHiddenObjects : new Map ( ) ,
managerHiddenObjectIds : new Set ( ) ,
managerHiddenCategories : new Set ( ) ,
@@ -1181,6 +1183,7 @@ function refreshLayerManager() {
} ) ;
applyManagedVisualOrder ( container ) ;
bindLayerManagerDrag ( container ) ;
bindLayerManagerMoveButtons ( container ) ;
}
function renderLayerManagerCategory ( category , records ) {
@@ -1188,10 +1191,13 @@ function renderLayerManagerCategory(category, records) {
group . className = "layer-manager-group" ;
group . dataset . dragType = "category" ;
group . dataset . categoryKey = category . key ;
const visible = ! lmeState . managerHiddenCategories . has ( category . key )
&& ( ! category . roots . length || category . roots . every ( layer => lmeState . map . hasLayer ( layer ) ) ) ;
group . innerHTML = ` <summary><button type="button" class="layer-drag-handle" aria-label="Trascina gruppo">☰</button><input type="checkbox" ${ visible ? "checked" : "" } aria-label="Mostra ${ escapeHtml ( category . label ) } "><span class="layer-manager-title"> ${ escapeHtml ( category . label ) } </span><span class="layer-manager-count"> ${ records . length } </span></summary><div class="layer-manager-children"></div> ` ;
const visibleCount = records . filter ( record => ! lmeState . managerHiddenObjectIds . has ( record . id ) ) . length ;
const categoryVisible = ! lmeState . managerHiddenCategories . has ( category . key )
&& ( ! category . roots . length || category . roots . some ( layer => lmeState . map . hasLayer ( layer ) ) ) ;
const visible = categoryVisible ;
group . innerHTML = ` <summary><button type="button" class="layer-drag-handle" aria-label="Trascina gruppo">☰</button><input type="checkbox" ${ visible ? "checked" : "" } aria-label="Mostra ${ escapeHtml ( category . label ) } "><span class="layer-manager-title"> ${ escapeHtml ( category . label ) } </span> ${ layerManagerMoveButtons ( "gruppo" ) } <span class="layer-manager-count"> ${ records . length } </span></summary><div class="layer-manager-children"></div> ` ;
const checkbox = group . querySelector ( "input" ) ;
checkbox . indeterminate = categoryVisible && records . length > 0 && visibleCount < records . length ;
checkbox . addEventListener ( "click" , event => event . stopPropagation ( ) ) ;
checkbox . addEventListener ( "change" , ( ) => setManagedCategoryVisible ( category , checkbox . checked ) ) ;
const children = group . querySelector ( ".layer-manager-children" ) ;
@@ -1217,7 +1223,7 @@ function renderLayerManagerBlock(category, source, records) {
block . dataset . blockKey = source ;
const visibleCount = records . filter ( record => ! lmeState . managerHiddenObjectIds . has ( record . id ) ) . length ;
const visible = visibleCount === records . length ;
block . innerHTML = ` <summary><button type="button" class="layer-drag-handle" aria-label="Trascina blocco">☰</button><input type="checkbox" ${ visible ? "checked" : "" } aria-label="Mostra blocco"><span class="layer-manager-title"> ${ escapeHtml ( source ) } </span><span class="layer-manager-count"> ${ records . length } </span></summary><div class="layer-manager-children"></div> ` ;
block . innerHTML = ` <summary><button type="button" class="layer-drag-handle" aria-label="Trascina blocco">☰</button><input type="checkbox" ${ visible ? "checked" : "" } aria-label="Mostra blocco"><span class="layer-manager-title"> ${ escapeHtml ( source ) } </span> ${ layerManagerMoveButtons ( "blocco" ) } <span class="layer-manager-count"> ${ records . length } </span></summary><div class="layer-manager-children"></div> ` ;
const checkbox = block . querySelector ( "input" ) ;
checkbox . indeterminate = visibleCount > 0 && ! visible ;
checkbox . addEventListener ( "click" , event => event . stopPropagation ( ) ) ;
@@ -1236,7 +1242,7 @@ function renderLayerManagerObject(record, index) {
object . dataset . dragType = "object" ;
object . dataset . objectId = record . id ;
const visible = ! lmeState . managerHiddenObjectIds . has ( record . id ) ;
object . innerHTML = ` <summary><button type="button" class="layer-drag-handle" aria-label="Trascina oggetto">☰</button><input type="checkbox" ${ visible ? "checked" : "" } aria-label="Mostra oggetto"><span class="layer-manager-title"> ${ escapeHtml ( managedObjectLabel ( record , index ) ) } </span><span class="layer-manager-count">› </span></summary><div class="layer-manager-details"></div> ` ;
object . innerHTML = ` <summary><button type="button" class="layer-drag-handle" aria-label="Trascina oggetto">☰</button><input type="checkbox" ${ visible ? "checked" : "" } aria-label="Mostra oggetto"><span class="layer-manager-title"> ${ escapeHtml ( managedObjectLabel ( record , index ) ) } </span> ${ layerManagerMoveButtons ( "oggetto" ) } <span class="layer-manager-count">› </span></summary><div class="layer-manager-details"></div> ` ;
const checkbox = object . querySelector ( "input" ) ;
checkbox . addEventListener ( "click" , event => event . stopPropagation ( ) ) ;
checkbox . addEventListener ( "change" , ( ) => setManagedObjectVisible ( record , checkbox . checked , true ) ) ;
@@ -1267,7 +1273,10 @@ function setManagedCategoryVisible(category, visible) {
if ( visible ) {
lmeState . managerHiddenCategories . delete ( category . key ) ;
category . roots . forEach ( layer => {
if ( layer && ! lmeState . map . hasLayer ( layer ) ) {
const objectId = managedLayerId ( layer , category . key ) ;
if ( layer
&& ! lmeState . managerHiddenObjectIds . has ( objectId )
&& ! lmeState . map . hasLayer ( layer ) ) {
layer . addTo ( lmeState . map ) ;
}
} ) ;
@@ -1278,15 +1287,23 @@ function setManagedCategoryVisible(category, visible) {
lmeState . map . removeLayer ( layer ) ;
}
} ) ;
if ( lmeState . managerHighlightedCategoryKey === category . key ) {
clearManagerHighlight ( ) ;
}
}
saveLayerManagerState ( ) ;
refreshImportedMeasurements ( ) ;
refreshDrawingMeasurements ( ) ;
refreshLayerManager ( ) ;
}
function setManagedObjectVisible ( record , visible , refresh = true ) {
if ( visible ) {
const hidden = lmeState . managerHiddenObjects . get ( record . id ) ;
if ( hidden ) {
hidden . parent . addLayer ( hidden . layer ) ;
if ( hidden . parent !== lmeState . map || managedCategoryEnabled ( record . categoryKey ) ) {
hidden . parent . addLayer ( hidden . layer ) ;
}
lmeState . managerHiddenObjects . delete ( record . id ) ;
}
lmeState . managerHiddenObjectIds . delete ( record . id ) ;
@@ -1294,6 +1311,9 @@ function setManagedObjectVisible(record, visible, refresh = true) {
lmeState . managerHiddenObjects . set ( record . id , record ) ;
lmeState . managerHiddenObjectIds . add ( record . id ) ;
record . parent . removeLayer ( record . layer ) ;
if ( lmeState . managerHighlightedObjectId === record . id ) {
clearManagerHighlight ( ) ;
}
}
saveLayerManagerState ( ) ;
refreshImportedMeasurements ( ) ;
@@ -1303,8 +1323,29 @@ function setManagedObjectVisible(record, visible, refresh = true) {
}
}
function managedCategoryEnabled ( categoryKey ) {
if ( lmeState . managerHiddenCategories . has ( categoryKey ) ) {
return false ;
}
if ( categoryKey === "gpsPosition" ) {
return lmeState . gpsPositionVisible ;
}
if ( categoryKey === "imported" ) {
return lmeState . importedVisible ;
}
if ( categoryKey === "importedSheets" ) {
return lmeState . importedSheetsVisible ;
}
if ( categoryKey === "selectedParcels" ) {
return lmeState . selectedParcelsVisible ;
}
return true ;
}
function highlightManagedObject ( record ) {
lmeState . managerHighlight . clearLayers ( ) ;
lmeState . managerHighlightedObjectId = record . id ;
lmeState . managerHighlightedCategoryKey = record . categoryKey ;
const geojson = record . layer . toGeoJSON ? . ( ) ;
if ( geojson ) {
L . geoJSON ( geojson , {
@@ -1325,6 +1366,16 @@ function highlightManagedObject(record) {
fitLayer ( record . layer ) ;
}
function clearManagerHighlight ( ) {
lmeState . managerHighlight ? . clearLayers ( ) ;
lmeState . managerHighlightedObjectId = null ;
lmeState . managerHighlightedCategoryKey = null ;
}
function layerManagerMoveButtons ( label ) {
return ` <span class="layer-move-buttons"><button type="button" class="layer-move-up" aria-label="Sposta ${ label } su" title="Sposta su">↑</button><button type="button" class="layer-move-down" aria-label="Sposta ${ label } giù" title="Sposta giù">↓</button></span> ` ;
}
function bindLayerManagerDrag ( container ) {
container . querySelectorAll ( ".layer-drag-handle" ) . forEach ( handle => {
handle . addEventListener ( "pointerdown" , event => {
@@ -1335,6 +1386,7 @@ function bindLayerManagerDrag(container) {
row . classList . add ( "layer-manager-dragging" ) ;
handle . setPointerCapture ? . ( event . pointerId ) ;
const move = moveEvent => {
moveEvent . preventDefault ( ) ;
const target = document . elementFromPoint ( moveEvent . clientX , moveEvent . clientY ) ? . closest ( ` [data-drag-type=" ${ row . dataset . dragType } "] ` ) ;
if ( ! target || target === row || target . parentElement !== list ) {
return ;
@@ -1344,14 +1396,37 @@ function bindLayerManagerDrag(container) {
} ;
const end = ( ) => {
row . classList . remove ( "layer-manager-dragging" ) ;
handle . removeEventListener ( "pointermove" , move ) ;
handle . removeEventListener ( "pointerup " , end ) ;
handle . removeEventListener ( "pointercancel " , end ) ;
handle . releasePointerCapture ? . ( event . pointerId ) ;
document . removeEventListener ( "pointermove " , move ) ;
document . removeEventListener ( "pointerup " , end ) ;
document . removeEventListener ( "pointercancel" , end ) ;
applyLayerManagerDomOrder ( container ) ;
} ;
handle . addEventListener ( "pointermove" , move ) ;
handle . addEventListener ( "pointerup" , end ) ;
handle . addEventListener ( "pointercancel" , end ) ;
document . addEventListener ( "pointermove" , move , { passive : false } ) ;
document . addEventListener ( "pointerup" , end ) ;
document . addEventListener ( "pointercancel" , end ) ;
} ) ;
} ) ;
}
function bindLayerManagerMoveButtons ( container ) {
container . querySelectorAll ( ".layer-move-up, .layer-move-down" ) . forEach ( button => {
button . addEventListener ( "click" , event => {
event . preventDefault ( ) ;
event . stopPropagation ( ) ;
const row = button . closest ( "[data-drag-type]" ) ;
const sibling = button . classList . contains ( "layer-move-up" )
? row . previousElementSibling
: row . nextElementSibling ;
if ( ! sibling || sibling . dataset . dragType !== row . dataset . dragType ) {
return ;
}
if ( button . classList . contains ( "layer-move-up" ) ) {
row . parentElement . insertBefore ( row , sibling ) ;
} else {
row . parentElement . insertBefore ( sibling , row ) ;
}
applyLayerManagerDomOrder ( container ) ;
} ) ;
} ) ;
}
@@ -1785,7 +1860,7 @@ function renderMeasurements(sourceGroup, targetGroup, visible, sourceType) {
return ;
}
targetGroup . clearLayers ( ) ;
if ( ! visible ) {
if ( ! visible || ! lmeState . map . hasLayer ( sourceGroup ) ) {
return ;
}
@@ -2343,7 +2418,7 @@ function resetLayerManagerProjectState() {
lmeState . managerHiddenObjectIds . clear ( ) ;
lmeState . managerHiddenCategories . clear ( ) ;
lmeState . managerObjectOrder = { } ;
lmeState . managerHighlight ? . clearLayers ( ) ;
clearManagerHighlight ( ) ;
}
function clearManagedCategoryState ( categoryKey ) {
@@ -2809,11 +2884,11 @@ function onGpsPosition(position) {
}
function updateGpsPositionLayers ( latlng , accuracy ) {
if ( ! lmeState . gpsPositionVisible ) {
return ;
}
let created = false ;
if ( ! lmeState . gpsMarker ) {
lmeState . gpsMarker = L . marker ( latlng , { pane : "gpsPositionPane" , title : "La tua posizione" } ) ;
lmeState . gpsMarker . lmeManagerId = "gps-position-marker" ;
lmeState . gpsMarker . lmeManagerLabel = "Posizione GPS" ;
lmeState . gpsAccuracy = L . circle ( latlng , {
pane : "gpsPositionPane" ,
radius : accuracy ,
@@ -2822,15 +2897,33 @@ function updateGpsPositionLayers(latlng, accuracy) {
fillColor : "#60a5fa" ,
fillOpacity : 0.16
} ) ;
lmeState . gpsAccuracy . lmeManagerId = "gps-accuracy-circle" ;
lmeState . gpsAccuracy . lmeManagerLabel = "Cerchio precisione GPS" ;
created = true ;
} else {
lmeState . gpsMarker . setLatLng ( latlng ) ;
lmeState . gpsAccuracy . setLatLng ( latlng ) . setRadius ( accuracy ) ;
}
if ( ! lmeState . map . hasLayer ( lmeState . gpsMarker ) ) {
const categoryVisible = lmeState . gpsPositionVisible
&& ! lmeState . managerHiddenCategories . has ( "gpsPosition" ) ;
if ( categoryVisible
&& ! lmeState . managerHiddenObjectIds . has ( "gps-position-marker" )
&& ! lmeState . map . hasLayer ( lmeState . gpsMarker ) ) {
lmeState . gpsMarker . addTo ( lmeState . map ) ;
} else if ( ( ! categoryVisible || lmeState . managerHiddenObjectIds . has ( "gps-position-marker" ) )
&& lmeState . map . hasLayer ( lmeState . gpsMarker ) ) {
lmeState . map . removeLayer ( lmeState . gpsMarker ) ;
}
if ( ! lmeState . map . hasLayer ( lmeState . gpsAccuracy ) ) {
if ( categoryVisible
&& ! lmeState . managerHiddenObjectIds . has ( "gps-accuracy-circle" )
&& ! lmeState . map . hasLayer ( lmeState . gpsAccuracy ) ) {
lmeState . gpsAccuracy . addTo ( lmeState . map ) ;
} else if ( ( ! categoryVisible || lmeState . managerHiddenObjectIds . has ( "gps-accuracy-circle" ) )
&& lmeState . map . hasLayer ( lmeState . gpsAccuracy ) ) {
lmeState . map . removeLayer ( lmeState . gpsAccuracy ) ;
}
if ( created ) {
refreshLayerManager ( ) ;
}
}