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