1 OSM.HistoryChangesetBboxLayer = L.FeatureGroup.extend({});
3 OSM.HistoryChangesetsLayer = L.FeatureGroup.extend({
4 _getSidebarRelativeClassName: function ({ sidebarRelativePosition }) {
5 if (sidebarRelativePosition > 0) {
6 return "changeset-above-sidebar-viewport";
7 } else if (sidebarRelativePosition < 0) {
8 return "changeset-below-sidebar-viewport";
10 return "changeset-in-sidebar-viewport";
14 _getAreaStyle: function (changeset) {
18 className: this._getSidebarRelativeClassName(changeset)
22 _getBorderStyle: function (changeset) {
25 color: "var(--changeset-border-color)",
27 className: this._getSidebarRelativeClassName(changeset)
31 _getHighlightStyle: function (changeset) {
35 color: "var(--changeset-border-color)",
36 fillColor: "var(--changeset-fill-color)",
38 className: this._getSidebarRelativeClassName(changeset) + " changeset-highlighted"
42 updateChangesets: function (map, changesets) {
43 this._changesets = new Map(changesets.map(changeset => [changeset.id, changeset]));
44 this.updateChangesetShapes(map);
47 updateChangesetShapes: function (map) {
48 for (const changeset of this._changesets.values()) {
49 const bottomLeft = map.project(L.latLng(changeset.bbox.minlat, changeset.bbox.minlon)),
50 topRight = map.project(L.latLng(changeset.bbox.maxlat, changeset.bbox.maxlon)),
51 width = topRight.x - bottomLeft.x,
52 height = bottomLeft.y - topRight.y,
53 minSize = 20; // Min width/height of changeset in pixels
55 if (width < minSize) {
56 bottomLeft.x -= ((minSize - width) / 2);
57 topRight.x += ((minSize - width) / 2);
60 if (height < minSize) {
61 bottomLeft.y += ((minSize - height) / 2);
62 topRight.y -= ((minSize - height) / 2);
65 changeset.bounds = L.latLngBounds(map.unproject(bottomLeft),
66 map.unproject(topRight));
69 this.updateChangesetLocations(map);
70 this.reorderChangesets();
73 updateChangesetLocations: function (map) {
74 const mapCenterLng = map.getCenter().lng;
76 for (const changeset of this._changesets.values()) {
77 const changesetSouthWest = changeset.bounds.getSouthWest();
78 const changesetNorthEast = changeset.bounds.getNorthEast();
79 const changesetCenterLng = (changesetSouthWest.lng + changesetNorthEast.lng) / 2;
80 const shiftInWorldCircumferences = Math.round((changesetCenterLng - mapCenterLng) / 360);
82 if (shiftInWorldCircumferences) {
83 changesetSouthWest.lng -= shiftInWorldCircumferences * 360;
84 changesetNorthEast.lng -= shiftInWorldCircumferences * 360;
86 for (const layer of this._bboxLayers) {
87 layer.getLayer(changeset.id)?.setBounds(changeset.bounds);
93 reorderChangesets: function () {
94 const changesetEntries = [...this._changesets];
95 changesetEntries.sort(([, a], [, b]) => {
96 const aInViewport = !a.sidebarRelativePosition;
97 const bInViewport = !b.sidebarRelativePosition;
98 if (aInViewport !== bInViewport) return aInViewport - bInViewport;
99 return b.bounds.getSize() - a.bounds.getSize();
101 this._changesets = new Map(changesetEntries);
103 for (const layer of this._bboxLayers) {
107 for (const changeset of this._changesets.values()) {
108 const rect = L.rectangle(changeset.bounds, this._getAreaStyle(changeset));
109 rect.id = changeset.id;
110 rect.addTo(this._areaLayer);
113 for (const changeset of this._changesets.values()) {
114 const rect = L.rectangle(changeset.bounds, this._getBorderStyle(changeset));
115 rect.id = changeset.id;
116 rect.addTo(this._borderLayer);
120 toggleChangesetHighlight: function (id, state) {
121 const changeset = this._changesets.get(id);
122 if (!changeset) return;
125 const highlightRect = L.rectangle(changeset.bounds, this._getHighlightStyle(changeset));
126 highlightRect.id = id;
127 this._highlightLayer.addLayer(highlightRect);
129 this._highlightLayer.removeLayer(id);
133 setChangesetSidebarRelativePosition: function (id, state) {
134 const changeset = this._changesets.get(id);
135 if (!changeset) return;
136 changeset.sidebarRelativePosition = state;
140 OSM.HistoryChangesetsLayer.addInitHook(function () {
141 this._changesets = new Map;
144 this._areaLayer = new OSM.HistoryChangesetBboxLayer().addTo(this),
145 this._borderLayer = new OSM.HistoryChangesetBboxLayer().addTo(this),
146 this._highlightLayer = new OSM.HistoryChangesetBboxLayer().addTo(this)
149 for (const layer of this._bboxLayers) {
150 layer.getLayerId = (layer) => layer.id;