1 OSM.HistoryChangesetBboxLayer = L.FeatureGroup.extend({
2 getLayerId: function (layer) {
6 updateChangesetLayerBounds: function (changeset) {
7 this.getLayer(changeset.id)?.setBounds(changeset.bounds);
11 OSM.HistoryChangesetsLayer = L.FeatureGroup.extend({
12 _getSidebarRelativeClassName: function ({ sidebarRelativePosition }) {
13 if (sidebarRelativePosition > 0) {
14 return "changeset-above-sidebar-viewport";
15 } else if (sidebarRelativePosition < 0) {
16 return "changeset-below-sidebar-viewport";
18 return "changeset-in-sidebar-viewport";
22 _getAreaStyle: function (changeset) {
26 className: this._getSidebarRelativeClassName(changeset)
30 _getBorderStyle: function (changeset) {
33 color: "var(--changeset-border-color)",
35 className: this._getSidebarRelativeClassName(changeset)
39 _getHighlightStyle: function (changeset) {
43 color: "var(--changeset-border-color)",
44 fillColor: "var(--changeset-fill-color)",
46 className: this._getSidebarRelativeClassName(changeset) + " changeset-highlighted"
50 updateChangesets: function (map, changesets) {
51 this._changesets = new Map(changesets.map(changeset => [changeset.id, changeset]));
52 this.updateChangesetShapes(map);
55 updateChangesetShapes: function (map) {
56 for (const changeset of this._changesets.values()) {
57 const bottomLeft = map.project(L.latLng(changeset.bbox.minlat, changeset.bbox.minlon)),
58 topRight = map.project(L.latLng(changeset.bbox.maxlat, changeset.bbox.maxlon)),
59 width = topRight.x - bottomLeft.x,
60 height = bottomLeft.y - topRight.y,
61 minSize = 20; // Min width/height of changeset in pixels
63 if (width < minSize) {
64 bottomLeft.x -= ((minSize - width) / 2);
65 topRight.x += ((minSize - width) / 2);
68 if (height < minSize) {
69 bottomLeft.y += ((minSize - height) / 2);
70 topRight.y -= ((minSize - height) / 2);
73 changeset.bounds = L.latLngBounds(map.unproject(bottomLeft),
74 map.unproject(topRight));
77 this.updateChangesetLocations(map);
78 this.reorderChangesets();
81 updateChangesetLocations: function (map) {
82 const mapCenterLng = map.getCenter().lng;
84 for (const changeset of this._changesets.values()) {
85 const changesetSouthWest = changeset.bounds.getSouthWest();
86 const changesetNorthEast = changeset.bounds.getNorthEast();
87 const changesetCenterLng = (changesetSouthWest.lng + changesetNorthEast.lng) / 2;
88 const shiftInWorldCircumferences = Math.round((changesetCenterLng - mapCenterLng) / 360);
90 if (shiftInWorldCircumferences) {
91 changesetSouthWest.lng -= shiftInWorldCircumferences * 360;
92 changesetNorthEast.lng -= shiftInWorldCircumferences * 360;
94 for (const layer of this._bboxLayers) {
95 layer.updateChangesetLayerBounds(changeset);
101 reorderChangesets: function () {
102 const changesetEntries = [...this._changesets];
103 changesetEntries.sort(([, a], [, b]) => {
104 const aInViewport = !a.sidebarRelativePosition;
105 const bInViewport = !b.sidebarRelativePosition;
106 if (aInViewport !== bInViewport) return aInViewport - bInViewport;
107 return b.bounds.getSize() - a.bounds.getSize();
109 this._changesets = new Map(changesetEntries);
111 for (const layer of this._bboxLayers) {
115 for (const changeset of this._changesets.values()) {
116 const rect = L.rectangle(changeset.bounds, this._getAreaStyle(changeset));
117 rect.id = changeset.id;
118 rect.addTo(this._areaLayer);
121 for (const changeset of this._changesets.values()) {
122 const rect = L.rectangle(changeset.bounds, this._getBorderStyle(changeset));
123 rect.id = changeset.id;
124 rect.addTo(this._borderLayer);
128 toggleChangesetHighlight: function (id, state) {
129 const changeset = this._changesets.get(id);
130 if (!changeset) return;
133 const highlightRect = L.rectangle(changeset.bounds, this._getHighlightStyle(changeset));
134 highlightRect.id = id;
135 this._highlightLayer.addLayer(highlightRect);
137 this._highlightLayer.removeLayer(id);
141 setChangesetSidebarRelativePosition: function (id, state) {
142 const changeset = this._changesets.get(id);
143 if (!changeset) return;
144 changeset.sidebarRelativePosition = state;
148 OSM.HistoryChangesetsLayer.addInitHook(function () {
149 this._changesets = new Map;
152 this._areaLayer = new OSM.HistoryChangesetBboxLayer().addTo(this),
153 this._borderLayer = new OSM.HistoryChangesetBboxLayer().addTo(this),
154 this._highlightLayer = new OSM.HistoryChangesetBboxLayer().addTo(this)