1 OSM.HistoryChangesetBboxLayer = L.FeatureGroup.extend({
 
   2   getLayerId: function (layer) {
 
   6   addChangesetLayer: function (changeset) {
 
   7     const style = this._getChangesetStyle(changeset);
 
   8     const rectangle = L.rectangle(changeset.bounds, style);
 
   9     rectangle.id = changeset.id;
 
  10     return this.addLayer(rectangle);
 
  13   updateChangesetLayerBounds: function (changeset) {
 
  14     this.getLayer(changeset.id)?.setBounds(changeset.bounds);
 
  17   _getSidebarRelativeClassName: function ({ sidebarRelativePosition }) {
 
  18     if (sidebarRelativePosition > 0) {
 
  19       return "changeset-above-sidebar-viewport";
 
  20     } else if (sidebarRelativePosition < 0) {
 
  21       return "changeset-below-sidebar-viewport";
 
  23       return "changeset-in-sidebar-viewport";
 
  28 OSM.HistoryChangesetBboxAreaLayer = OSM.HistoryChangesetBboxLayer.extend({
 
  29   _getChangesetStyle: function (changeset) {
 
  33       className: this._getSidebarRelativeClassName(changeset)
 
  38 OSM.HistoryChangesetBboxOutlineLayer = OSM.HistoryChangesetBboxLayer.extend({
 
  39   _getChangesetStyle: function (changeset) {
 
  42       color: "var(--changeset-outline-color)",
 
  44       className: this._getSidebarRelativeClassName(changeset)
 
  49 OSM.HistoryChangesetBboxBorderLayer = OSM.HistoryChangesetBboxLayer.extend({
 
  50   _getChangesetStyle: function (changeset) {
 
  53       color: "var(--changeset-border-color)",
 
  55       className: this._getSidebarRelativeClassName(changeset)
 
  60 OSM.HistoryChangesetBboxHighlightAreaLayer = OSM.HistoryChangesetBboxLayer.extend({
 
  61   _getChangesetStyle: function (changeset) {
 
  65       fillColor: "var(--changeset-fill-color)",
 
  67       className: this._getSidebarRelativeClassName(changeset)
 
  72 OSM.HistoryChangesetBboxHighlightOutlineLayer = OSM.HistoryChangesetBboxLayer.extend({
 
  73   _getChangesetStyle: function (changeset) {
 
  76       weight: changeset.sidebarRelativePosition === 0 ? 8 : 6,
 
  77       color: "var(--changeset-outline-color)",
 
  79       className: this._getSidebarRelativeClassName(changeset) + " changeset-highlight-outline"
 
  84 OSM.HistoryChangesetBboxHighlightBorderLayer = OSM.HistoryChangesetBboxLayer.extend({
 
  85   _getChangesetStyle: function (changeset) {
 
  89       color: "var(--changeset-border-color)",
 
  91       className: this._getSidebarRelativeClassName(changeset)
 
  96 OSM.HistoryChangesetsLayer = L.FeatureGroup.extend({
 
  97   updateChangesets: function (map, changesets) {
 
  98     this._changesets = new Map(changesets.map(changeset => [changeset.id, changeset]));
 
  99     this.updateChangesetsGeometry(map);
 
 102   updateChangesetsGeometry: function (map) {
 
 103     const changesetSizeLowerBound = 20, // Min width/height of changeset in pixels
 
 104           mapViewExpansion = 2; // Half of bbox border+outline width in pixels
 
 106     const mapViewCenterLng = map.getCenter().lng,
 
 107           mapViewPixelBounds = map.getPixelBounds();
 
 109     mapViewPixelBounds.min.x -= mapViewExpansion;
 
 110     mapViewPixelBounds.min.y -= mapViewExpansion;
 
 111     mapViewPixelBounds.max.x += mapViewExpansion;
 
 112     mapViewPixelBounds.max.y += mapViewExpansion;
 
 114     for (const changeset of this._changesets.values()) {
 
 115       const changesetNorthWestLatLng = L.latLng(changeset.bbox.maxlat, changeset.bbox.minlon),
 
 116             changesetSouthEastLatLng = L.latLng(changeset.bbox.minlat, changeset.bbox.maxlon),
 
 117             changesetCenterLng = (changesetNorthWestLatLng.lng + changesetSouthEastLatLng.lng) / 2,
 
 118             shiftInWorldCircumferences = Math.round((changesetCenterLng - mapViewCenterLng) / 360);
 
 120       if (shiftInWorldCircumferences) {
 
 121         changesetNorthWestLatLng.lng -= shiftInWorldCircumferences * 360;
 
 122         changesetSouthEastLatLng.lng -= shiftInWorldCircumferences * 360;
 
 125       const changesetMinCorner = map.project(changesetNorthWestLatLng),
 
 126             changesetMaxCorner = map.project(changesetSouthEastLatLng),
 
 127             changesetSizeX = changesetMaxCorner.x - changesetMinCorner.x,
 
 128             changesetSizeY = changesetMaxCorner.y - changesetMinCorner.y;
 
 130       if (changesetSizeX < changesetSizeLowerBound) {
 
 131         changesetMinCorner.x -= (changesetSizeLowerBound - changesetSizeX) / 2;
 
 132         changesetMaxCorner.x += (changesetSizeLowerBound - changesetSizeX) / 2;
 
 135       if (changesetSizeY < changesetSizeLowerBound) {
 
 136         changesetMinCorner.y -= (changesetSizeLowerBound - changesetSizeY) / 2;
 
 137         changesetMaxCorner.y += (changesetSizeLowerBound - changesetSizeY) / 2;
 
 140       changeset.bounds = L.latLngBounds(map.unproject(changesetMinCorner),
 
 141                                         map.unproject(changesetMaxCorner));
 
 143       const changesetPixelBounds = L.bounds(changesetMinCorner, changesetMaxCorner);
 
 145       changeset.hasEdgesInMapView = changesetPixelBounds.overlaps(mapViewPixelBounds) &&
 
 146                                     !changesetPixelBounds.contains(mapViewPixelBounds);
 
 149     this.updateChangesetsOrder();
 
 152   updateChangesetsOrder: function () {
 
 153     const changesetEntries = [...this._changesets];
 
 154     changesetEntries.sort(([, a], [, b]) => b.bounds.getSize() - a.bounds.getSize());
 
 155     this._changesets = new Map(changesetEntries);
 
 157     for (const layer of this._bboxLayers) {
 
 161     for (const changeset of this._changesets.values()) {
 
 162       if (changeset.sidebarRelativePosition !== 0 && changeset.hasEdgesInMapView) {
 
 163         this._areaLayer.addChangesetLayer(changeset);
 
 167     for (const changeset of this._changesets.values()) {
 
 168       if (changeset.sidebarRelativePosition === 0 && changeset.hasEdgesInMapView) {
 
 169         this._areaLayer.addChangesetLayer(changeset);
 
 173     for (const changeset of this._changesets.values()) {
 
 174       if (changeset.sidebarRelativePosition !== 0) {
 
 175         this._borderLayer.addChangesetLayer(changeset);
 
 179     for (const changeset of this._changesets.values()) {
 
 180       if (changeset.sidebarRelativePosition === 0) {
 
 181         this._outlineLayer.addChangesetLayer(changeset);
 
 185     for (const changeset of this._changesets.values()) {
 
 186       if (changeset.sidebarRelativePosition === 0) {
 
 187         this._borderLayer.addChangesetLayer(changeset);
 
 192   toggleChangesetHighlight: function (id, state) {
 
 193     const changeset = this._changesets.get(id);
 
 194     if (!changeset) return;
 
 197       this._highlightAreaLayer.addChangesetLayer(changeset);
 
 198       this._highlightOutlineLayer.addChangesetLayer(changeset);
 
 199       this._highlightBorderLayer.addChangesetLayer(changeset);
 
 201       this._highlightAreaLayer.removeLayer(id);
 
 202       this._highlightOutlineLayer.removeLayer(id);
 
 203       this._highlightBorderLayer.removeLayer(id);
 
 207   setChangesetSidebarRelativePosition: function (id, state) {
 
 208     const changeset = this._changesets.get(id);
 
 209     if (!changeset) return;
 
 210     changeset.sidebarRelativePosition = state;
 
 214 OSM.HistoryChangesetsLayer.addInitHook(function () {
 
 215   this._changesets = new Map;
 
 218     this._areaLayer = new OSM.HistoryChangesetBboxAreaLayer().addTo(this),
 
 219     this._outlineLayer = new OSM.HistoryChangesetBboxOutlineLayer().addTo(this),
 
 220     this._borderLayer = new OSM.HistoryChangesetBboxBorderLayer().addTo(this),
 
 221     this._highlightAreaLayer = new OSM.HistoryChangesetBboxHighlightAreaLayer().addTo(this),
 
 222     this._highlightOutlineLayer = new OSM.HistoryChangesetBboxHighlightOutlineLayer().addTo(this),
 
 223     this._highlightBorderLayer = new OSM.HistoryChangesetBboxHighlightBorderLayer().addTo(this)