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