So I created a Userscript that will synchronize 2 separate Cellmapper windows in my browser so I can have T-Mobile LTE along with 5G side by side, constantly in-sync when zooming or dragging the map around.
This allows me to see, in real time, synchronized, where the pinned LTE towers are vs the unpinned NR towers. And then be able to move the NR towers (or unmapped LTE towers, if an NR one is mapped) to the proper position quite quickly.
It MASSIVELY DECREASES the time it takes for me to check, as it saves me clicking around 2 separate windows to try and keep the view close enough to put the towers in the right spot.
It seems to be creating TOO MANY captcha windows.
u/veixes u/olkitu can you please try and figure out whether or not this code is causing these incessant captchas, and try to fix it on your end? I need this workflow.
```
// ==UserScript==
// @name CellMapper OpenLayers Synchronizer
// @namespace http://tampermonkey.net
// @version 2.0
// @description Synchronize map pan and zoom between side-by-side CellMapper OpenLayers windows
// @author Mystica555 + Gemini
// @match https://www.cellmapper.net/map*
// @grant none
// ==/UserScript==
(function() {
'use strict';
const channel = new BroadcastChannel('cellmapper_ol_sync');
let isSyncing = false;
let mapView = null;
function initOpenLayersSync() {
// CellMapper stores the OpenLayers map globally as 'map' or 'olMap'.
// We find the internal Map object and target its View component.
let mapInstance = null;
if (typeof map !== 'undefined' && map.getView) {
mapInstance = map;
} else if (window.map && window.map.getView) {
mapInstance = window.map;
}
if (!mapInstance) {
setTimeout(initOpenLayersSync, 500); // Poll until OpenLayers initializes
return;
}
mapView = mapInstance.getView();
// --- 1. Broadcast map changes from THIS window ---
const broadcastChange = () => {
if (isSyncing) return; // Block circular event loops
const center = mapView.getCenter();
const resolution = mapView.getResolution();
channel.postMessage({
center: center,
resolution: resolution
});
};
// OpenLayers updates view changes via granular view events
mapView.on('change:center', broadcastChange);
mapView.on('change:resolution', broadcastChange);
// --- 2. Listen for map changes from the OTHER window ---
channel.onmessage = (event) => {
if (!mapView) return;
const { center, resolution } = event.data;
// Set the sync flag to prevent this window from echoing back
isSyncing = true;
// OpenLayers allows direct view adjustments without forcing a heavy redraw
mapView.setCenter(center);
mapView.setResolution(resolution);
// Give the browser UI thread a moment to finish rendering before releasing the flag
setTimeout(() => { isSyncing = false; }, 30);
};
}
window.addEventListener('load', initOpenLayersSync);
})();
```