]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/index_modules/new_note.js
Merge pull request #7302 from tomhughes/terms-locale
[rails.git] / app / assets / javascripts / index_modules / new_note.js
1 export default function (map) {
2   const noteLayer = map.noteLayer,
3         content = $("#sidebar_content"),
4         page = {},
5         control = $(".control-note"),
6         addNoteButton = control.find(".control-button");
7   let newNoteMarker,
8       halo,
9       errorPanel,
10       errorPanelDetail;
11
12   function createNote(location, text) {
13     return fetch("/api/0.6/notes.json", {
14       method: "POST",
15       headers: { ...OSM.oauth },
16       body: new URLSearchParams({
17         lat: location.lat,
18         lon: location.lng,
19         text
20       })
21     })
22       .then(resp => {
23         if (resp.ok) return resp.json();
24         throw new Error(`HTTP Error ${resp.status} ${resp.statusText}`);
25       });
26   }
27
28   function addCreatedNoteMarker(feature) {
29     const marker = L.marker(feature.geometry.coordinates.reverse(), {
30       icon: OSM.noteMarkers[feature.properties.status],
31       opacity: 0.9,
32       interactive: true
33     });
34     marker.id = feature.properties.id;
35     marker.addTo(noteLayer);
36   }
37
38   function addHalo(latlng) {
39     if (halo) map.removeLayer(halo);
40
41     halo = L.circleMarker(latlng, {
42       weight: 2.5,
43       radius: 20,
44       fillOpacity: 0.5,
45       color: "#FF6200"
46     });
47
48     map.addLayer(halo);
49   }
50
51   function removeHalo() {
52     if (halo) map.removeLayer(halo);
53     halo = null;
54   }
55
56   function addNewNoteMarker(latlng) {
57     if (newNoteMarker) map.removeLayer(newNoteMarker);
58
59     newNoteMarker = L.marker(latlng, {
60       icon: OSM.noteMarkers.new,
61       opacity: 0.9,
62       draggable: true
63     });
64
65     newNoteMarker.on("dragstart", removeHalo);
66     newNoteMarker.on("dragend", function () {
67       removeHalo();
68       addHalo(newNoteMarker.getLatLng());
69     });
70
71     newNoteMarker.addTo(map);
72     addHalo(newNoteMarker.getLatLng());
73
74     newNoteMarker.on("dragend", function () {
75       content.find("textarea").trigger("focus");
76     });
77   }
78
79   function removeNewNoteMarker() {
80     removeHalo();
81     if (newNoteMarker) map.removeLayer(newNoteMarker);
82     newNoteMarker = null;
83   }
84
85   function moveNewNoteMarkerToClick(e) {
86     if (newNoteMarker) newNoteMarker.setLatLng(e.latlng);
87     if (halo) halo.setLatLng(e.latlng);
88     content.find("textarea").trigger("focus");
89   }
90
91   function updateControls() {
92     const zoomedOut = addNoteButton.hasClass("disabled");
93     const withoutText = content.find("textarea").val() === "";
94
95     content.find("#new-note-zoom-warning").prop("hidden", !zoomedOut);
96     content.find("input[type=submit]").prop("disabled", zoomedOut || withoutText);
97     if (newNoteMarker) newNoteMarker.setOpacity(zoomedOut ? 0.5 : 0.9);
98   }
99
100   page.load = function (path) {
101     OSM.loadSidebarContent(path)
102       .then(() => page.init(path));
103   };
104
105   page.init = function (path) {
106     control.addClass("active");
107
108     map.addLayer(noteLayer);
109
110     const params = new URLSearchParams(path.substring(path.indexOf("?")));
111     let markerLatlng;
112
113     if (params.has("lat") && params.has("lon")) {
114       markerLatlng = { lat: params.get("lat"), lng: params.get("lon") };
115     } else {
116       markerLatlng = map.getCenter();
117     }
118
119     map.panInside(markerLatlng, {
120       padding: [50, 50]
121     });
122
123     addNewNoteMarker(markerLatlng);
124
125     content.find("textarea")
126       .on("input", updateControls)
127       .attr("readonly", "readonly") // avoid virtual keyboard popping up on focus
128       .trigger("focus")
129       .removeAttr("readonly");
130
131     content.find("input[type=submit]").on("click", function (e) {
132       const location = newNoteMarker.getLatLng().wrap();
133       const text = content.find("textarea").val();
134
135       errorPanel = content.find(".new-note-error");
136       errorPanel.addClass("d-none");
137       errorPanelDetail = errorPanel.find(".new-note-error-detail");
138
139       e.preventDefault();
140       $(this).prop("disabled", true);
141       newNoteMarker.options.draggable = false;
142       newNoteMarker.dragging.disable();
143
144       createNote(location, text)
145         .then(feature => {
146           if (typeof OSM.user === "undefined") {
147             const anonymousNotesCount = Number(OSM.cookies.get("_osm_anonymous_notes_count")) || 0;
148             OSM.cookies.set("_osm_anonymous_notes_count", anonymousNotesCount + 1, { expires: 14 });
149           }
150           content.find("textarea").val("");
151           addCreatedNoteMarker(feature);
152           OSM.router.route("/note/" + feature.properties.id);
153         })
154         .catch(err => {
155           errorPanel.removeClass("d-none");
156           errorPanelDetail.text(err.message || err);
157           updateControls();
158         });
159     });
160
161     map.on("click", moveNewNoteMarkerToClick);
162     addNoteButton.on("disabled enabled", updateControls);
163     updateControls();
164
165     return map.getState();
166   };
167
168   page.unload = function () {
169     map.off("click", moveNewNoteMarkerToClick);
170     addNoteButton.off("disabled enabled", updateControls);
171     removeNewNoteMarker();
172     control.removeClass("active");
173   };
174
175   return page;
176 }