9fb03bb0dd62af9ad4ec7c5be0a75a70fd0b20b4
[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       updateNote(marker, e.target.form, $(e.target).data("url"));
165     });
166
167     return content[0];
168   }
169
170   function createNote(marker, form, url) {
171     var location = marker.getLatLng();
172
173     $(form).find("input[type=submit]").prop("disabled", true);
174
175     $.ajax({
176       url: url,
177       type: "POST",
178       oauth: true,
179       data: {
180         lat: location.lat,
181         lon: location.lng,
182         text: $(form.text).val()
183       },
184       success: function (feature) {
185         notes[feature.properties.id] = updateMarker(marker, feature);
186         newNote = null;
187
188         $("#createnoteanchor").removeClass("disabled").addClass("geolink");
189       }
190     });
191   }
192
193   function updateNote(marker, form, url) {
194     $(form).find("input[type=submit]").prop("disabled", true);
195
196     $.ajax({
197       url: url,
198       type: "POST",
199       oauth: true,
200       data: {
201         text: $(form.text).val()
202       },
203       success: function (feature) {
204         var popupContent = createPopupContent(marker, feature.properties);
205
206         marker.setIcon(noteIcons[feature.properties.status]);
207         marker._popup.setContent(popupContent);
208       }
209     });
210   }
211
212   $("#createnoteanchor").click(function (e) {
213     e.preventDefault();
214
215     if ($(e.target).hasClass("disabled")) return;
216
217     $(e.target).removeClass("geolink").addClass("disabled");
218
219     map.addLayer(noteLayer);
220
221     var mapSize = map.getSize();
222     var markerPosition;
223
224     if (mapSize.y > 800)
225     {
226       markerPosition = [mapSize.x / 2, mapSize.y / 2];
227     }
228     else if (mapSize.y > 400)
229     {
230       markerPosition = [mapSize.x / 2, 400];
231     }
232     else
233     {
234       markerPosition = [mapSize.x / 2, mapSize.y];
235     }
236
237     newNote = L.marker(map.containerPointToLatLng(markerPosition), {
238       icon: noteIcons["new"],
239       opacity: 0.7,
240       draggable: true
241     });
242
243     var popupContent = $(JST["templates/notes/new"]({ create_url: $(e.target).attr("href") }));
244
245     popupContent.find("textarea").on("input", function (e) {
246       var form = e.target.form;
247
248       if ($(e.target).val() == "") {
249         $(form.add).prop("disabled", true);
250       } else {
251         $(form.add).prop("disabled", false);
252       }
253     });
254
255     popupContent.find("input[type=submit]").on("click", function (e) {
256       e.preventDefault();
257       createNote(newNote, e.target.form, $(e.target).data("url"));
258     });
259
260     newNote.addTo(noteLayer).bindPopup(popupContent[0], popupOptions()).openPopup();
261
262     newNote.on("remove", function (e) {
263       $("#createnoteanchor").removeClass("disabled").addClass("geolink");
264     });
265
266     newNote.on("dragstart", function (e) {
267       $(newNote).stopTime("removenote");
268     });
269
270     newNote.on("dragend", function (e) {
271       e.target.openPopup();
272     });
273   });
274 });