]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/index/notes.js.erb
Replace note markers with ones styled like the other markers
[rails.git] / app / assets / javascripts / index / notes.js.erb
1 //= require templates/notes/show
2 //= require templates/notes/new
3
4 $(document).ready(function () {
5   var params = OSM.mapParams();
6
7   var noteIcons = {
8     "new": L.icon({
9       iconUrl: "<%= image_path 'new_note_marker.png' %>",
10       iconSize: [25, 40],
11       iconAnchor: [12, 40]
12     }),
13     "open": L.icon({
14       iconUrl: "<%= image_path 'open_note_marker.png' %>",
15       iconSize: [25, 40],
16       iconAnchor: [12, 40]
17     }),
18     "closed": L.icon({
19       iconUrl: "<%= image_path 'closed_note_marker.png' %>",
20       iconSize: [25, 40],
21       iconAnchor: [12, 40]
22     })
23   };
24
25   var noteLayer = new L.LayerGroup();
26   var notes = {};
27   var newNote;
28
29   layers.push({
30     layer: noteLayer,
31     layerCode: "N"
32   });
33
34   map.on("layeradd", function (e) {
35     if (e.layer == noteLayer) {
36       loadNotes();
37       map.on("moveend", loadNotes);
38     }
39   });
40
41   map.on("layerremove", function (e) {
42     if (e.layer == noteLayer) {
43       map.off("moveend", loadNotes);
44       noteLayer.clearLayers();
45       notes = {};
46     }
47   });
48
49   // Don't focus the text area on touch devices to avoid flashing the keyboard
50   if (!('ontouchstart' in document.documentElement)) {
51     map.on("popupopen", function (e) {
52       $(e.popup._container).find(".comment").focus();
53     });
54   }
55
56   map.on("popupclose", function (e) {
57     if (newNote && e.popup == newNote._popup) {
58       $(newNote).oneTime(10, "removenote", function () {
59         map.removeLayer(newNote);
60         newNote = null;
61       });
62     }
63   });
64
65   if (OSM.STATUS != 'api_offline' && OSM.STATUS != 'database_offline') {
66     map.layersControl.addOverlay(noteLayer, I18n.t("browse.start_rjs.notes_layer_name"));
67
68     if (params.layers) setMapLayers(params.layers);
69     if (params.notes) map.addLayer(noteLayer);
70
71     if (params.note) {
72       $.ajax({
73         url: "/api/" + OSM.API_VERSION + "/notes/" + params.note + ".json",
74         success: function (feature) {
75           var marker = updateMarker(notes[feature.properties.id], feature);
76
77           notes[feature.properties.id] = marker;
78
79           map.addLayer(noteLayer);
80           marker.openPopup();
81         }
82       });
83     }
84   }
85
86   function updateMarker(marker, feature) {
87     if (marker)
88     {
89       marker.setIcon(noteIcons[feature.properties.status]);
90       marker._popup.setContent(createPopupContent(
91         marker, feature.properties, 
92         $(marker._popup._content).find("textarea").val()
93       ));
94     }
95     else
96     {
97       marker = L.marker(feature.geometry.coordinates.reverse(), {
98         icon: noteIcons[feature.properties.status],
99         opacity: 0.9
100       });
101
102       marker.addTo(noteLayer).bindPopup(
103         createPopupContent(marker, feature.properties),
104         popupOptions()
105       );
106     }
107
108     return marker;
109   }
110
111   var noteLoader;
112
113   function loadNotes() {
114     var bounds = map.getBounds();
115     var size = bounds.getSize();
116
117     if (size <= OSM.MAX_NOTE_REQUEST_AREA) {
118       var url = "/api/" + OSM.API_VERSION + "/notes.json?bbox=" + bounds.toBBOX();
119
120       if (noteLoader) noteLoader.abort();
121
122       noteLoader = $.ajax({
123         url: url,
124         success: function (json) {
125           var oldNotes = notes;
126
127           notes = {};
128
129           json.features.forEach(function (feature) {
130             var marker = oldNotes[feature.properties.id];
131
132             delete oldNotes[feature.properties.id];
133
134             notes[feature.properties.id] = updateMarker(marker, feature);
135           });
136
137           for (id in oldNotes) {
138             noteLayer.removeLayer(oldNotes[id]);
139           }
140
141           noteLoader = null;
142         }
143       });
144     }
145   };
146
147   function popupOptions() {
148     var mapSize = map.getSize();
149
150     return {
151       minWidth: 320,
152       maxWidth: mapSize.y * 1 / 3,
153       maxHeight: mapSize.y * 2 / 3,
154       offset: new L.Point(0, -40),
155       autoPanPadding: new L.Point(60, 40)
156     };
157   }
158
159   function createPopupContent(marker, properties, comment) {
160     var content = $(JST["templates/notes/show"]({ note: properties }));
161
162     content.find("textarea").on("input", function (e) {
163       var form = e.target.form;
164
165       if ($(e.target).val() == "") {
166         $(form.close).val(I18n.t("javascripts.notes.show.resolve"));
167         $(form.comment).prop("disabled", true);
168       } else {
169         $(form.close).val(I18n.t("javascripts.notes.show.comment_and_resolve"));
170         $(form.comment).prop("disabled", false);
171       }
172     });
173
174     content.find("input[type=submit]").on("click", function (e) {
175       e.preventDefault();
176       var data = $(e.target).data();
177       updateNote(marker, e.target.form, data.method, data.url);
178     });
179
180     if (comment) {
181       content.find("textarea").val(comment).trigger("input");
182     }
183
184     return content[0];
185   }
186
187   function createNote(marker, form, url) {
188     var location = marker.getLatLng();
189
190     marker.options.draggable = false;
191     marker.dragging.disable();
192
193     $(form).find("input[type=submit]").prop("disabled", true);
194
195     $.ajax({
196       url: url,
197       type: "POST",
198       oauth: true,
199       data: {
200         lat: location.lat,
201         lon: location.lng,
202         text: $(form.text).val()
203       },
204       success: function (feature) {
205         $(marker._popup._content).find("textarea").val("");
206
207         notes[feature.properties.id] = updateMarker(marker, feature);
208         newNote = null;
209
210         $("#createnoteanchor").removeClass("disabled").addClass("geolink");
211       }
212     });
213   }
214
215   function updateNote(marker, form, method, url) {
216     $(form).find("input[type=submit]").prop("disabled", true);
217
218     $.ajax({
219       url: url,
220       type: method,
221       oauth: true,
222       data: {
223         text: $(form.text).val()
224       },
225       success: function (feature) {
226         if (feature.properties.status == "hidden") {
227           noteLayer.removeLayer(marker);
228
229           delete notes[feature.properties.id];
230         } else {
231           var popupContent = createPopupContent(marker, feature.properties);
232
233           marker.setIcon(noteIcons[feature.properties.status]);
234           marker._popup.setContent(popupContent);
235         }
236       }
237     });
238   }
239
240   $(".leaflet-control-attribution").on("click", "#createnoteanchor", function (e) {
241     e.preventDefault();
242
243     if ($(e.target).hasClass("disabled")) return;
244
245     $(e.target).removeClass("geolink").addClass("disabled");
246
247     map.addLayer(noteLayer);
248
249     var mapSize = map.getSize();
250     var markerPosition;
251
252     if (mapSize.y > 800)
253     {
254       markerPosition = [mapSize.x / 2, mapSize.y / 2];
255     }
256     else if (mapSize.y > 400)
257     {
258       markerPosition = [mapSize.x / 2, 400];
259     }
260     else
261     {
262       markerPosition = [mapSize.x / 2, mapSize.y];
263     }
264
265     newNote = L.marker(map.containerPointToLatLng(markerPosition), {
266       icon: noteIcons["new"],
267       opacity: 0.9,
268       draggable: true
269     });
270
271     var popupContent = $(JST["templates/notes/new"]({ create_url: $(e.target).attr("href") }));
272
273     popupContent.find("textarea").on("input", function (e) {
274       var form = e.target.form;
275
276       if ($(e.target).val() == "") {
277         $(form.add).prop("disabled", true);
278       } else {
279         $(form.add).prop("disabled", false);
280       }
281     });
282
283     popupContent.find("input[type=submit]").on("click", function (e) {
284       e.preventDefault();
285       createNote(newNote, e.target.form, $(e.target).data("url"));
286     });
287
288     newNote.addTo(noteLayer).bindPopup(popupContent[0], popupOptions()).openPopup();
289
290     newNote.on("remove", function (e) {
291       $("#createnoteanchor").removeClass("disabled").addClass("geolink");
292     });
293
294     newNote.on("dragstart", function (e) {
295       $(newNote).stopTime("removenote");
296     });
297
298     newNote.on("dragend", function (e) {
299       e.target.openPopup();
300     });
301   });
302 });