b7331005bc6a99d0a4f740fd5bca1a80cb4d78c7
[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   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(marker, feature.properties));
91     }
92     else
93     {
94       marker = L.marker(feature.geometry.coordinates.reverse(), {
95         icon: noteIcons[feature.properties.status],
96         opacity: 0.7
97       });
98
99       marker.addTo(noteLayer).bindPopup(
100         createPopupContent(marker, feature.properties),
101         popupOptions()
102       );
103     }
104
105     return marker;
106   }
107
108   var noteLoader;
109
110   function loadNotes() {
111     var bounds = map.getBounds();
112     var size = bounds.getSize();
113
114     if (size <= OSM.MAX_NOTE_REQUEST_AREA) {
115       var url = "/api/" + OSM.API_VERSION + "/notes.json?bbox=" + bounds.toBBOX();
116
117       if (noteLoader) noteLoader.abort();
118
119       noteLoader = $.ajax({
120         url: url,
121         success: function (json) {
122           var oldNotes = notes;
123
124           notes = {};
125
126           json.features.forEach(function (feature) {
127             var marker = oldNotes[feature.properties.id];
128
129             delete oldNotes[feature.properties.id];
130
131             notes[feature.properties.id] = updateMarker(marker, feature);
132           });
133
134           for (id in oldNotes) {
135             noteLayer.removeLayer(oldNotes[id]);
136           }
137
138           noteLoader = null;
139         }
140       });
141     }
142   };
143
144   function popupOptions() {
145     var mapSize = map.getSize();
146
147     return {
148       minWidth: 320,
149       maxWidth: mapSize.y * 1 / 3,
150       maxHeight: mapSize.y * 2 / 3,
151       offset: new L.Point(0, -3),
152       autoPanPadding: new L.Point(60, 40)
153     };
154   }
155
156   function createPopupContent(marker, properties) {
157     var content = $(JST["templates/notes/show"]({ note: properties }));
158
159     content.find("textarea").on("input", function (e) {
160       var form = e.target.form;
161
162       if ($(e.target).val() == "") {
163         $(form.close).val(I18n.t("javascripts.notes.show.resolve"));
164         $(form.comment).prop("disabled", true);
165       } else {
166         $(form.close).val(I18n.t("javascripts.notes.show.comment_and_resolve"));
167         $(form.comment).prop("disabled", false);
168       }
169     });
170
171     content.find("input[type=submit]").on("click", function (e) {
172       e.preventDefault();
173       var data = $(e.target).data();
174       updateNote(marker, e.target.form, data.method, data.url);
175     });
176
177     return content[0];
178   }
179
180   function createNote(marker, form, url) {
181     var location = marker.getLatLng();
182
183     marker.options.draggable = false;
184     marker.dragging.disable();
185
186     $(form).find("input[type=submit]").prop("disabled", true);
187
188     $.ajax({
189       url: url,
190       type: "POST",
191       oauth: true,
192       data: {
193         lat: location.lat,
194         lon: location.lng,
195         text: $(form.text).val()
196       },
197       success: function (feature) {
198         notes[feature.properties.id] = updateMarker(marker, feature);
199         newNote = null;
200
201         $("#createnoteanchor").removeClass("disabled").addClass("geolink");
202       }
203     });
204   }
205
206   function updateNote(marker, form, method, url) {
207     $(form).find("input[type=submit]").prop("disabled", true);
208
209     $.ajax({
210       url: url,
211       type: method,
212       oauth: true,
213       data: {
214         text: $(form.text).val()
215       },
216       success: function (feature) {
217         if (feature.properties.status == "hidden") {
218           noteLayer.removeLayer(marker);
219
220           delete notes[feature.properties.id];
221         } else {
222           var popupContent = createPopupContent(marker, feature.properties);
223
224           marker.setIcon(noteIcons[feature.properties.status]);
225           marker._popup.setContent(popupContent);
226         }
227       }
228     });
229   }
230
231   $(".leaflet-control-attribution").on("click", "#createnoteanchor", function (e) {
232     e.preventDefault();
233
234     if ($(e.target).hasClass("disabled")) return;
235
236     $(e.target).removeClass("geolink").addClass("disabled");
237
238     map.addLayer(noteLayer);
239
240     var mapSize = map.getSize();
241     var markerPosition;
242
243     if (mapSize.y > 800)
244     {
245       markerPosition = [mapSize.x / 2, mapSize.y / 2];
246     }
247     else if (mapSize.y > 400)
248     {
249       markerPosition = [mapSize.x / 2, 400];
250     }
251     else
252     {
253       markerPosition = [mapSize.x / 2, mapSize.y];
254     }
255
256     newNote = L.marker(map.containerPointToLatLng(markerPosition), {
257       icon: noteIcons["new"],
258       opacity: 0.7,
259       draggable: true
260     });
261
262     var popupContent = $(JST["templates/notes/new"]({ create_url: $(e.target).attr("href") }));
263
264     popupContent.find("textarea").on("input", function (e) {
265       var form = e.target.form;
266
267       if ($(e.target).val() == "") {
268         $(form.add).prop("disabled", true);
269       } else {
270         $(form.add).prop("disabled", false);
271       }
272     });
273
274     popupContent.find("input[type=submit]").on("click", function (e) {
275       e.preventDefault();
276       createNote(newNote, e.target.form, $(e.target).data("url"));
277     });
278
279     newNote.addTo(noteLayer).bindPopup(popupContent[0], popupOptions()).openPopup();
280
281     newNote.on("remove", function (e) {
282       $("#createnoteanchor").removeClass("disabled").addClass("geolink");
283     });
284
285     newNote.on("dragstart", function (e) {
286       $(newNote).stopTime("removenote");
287     });
288
289     newNote.on("dragend", function (e) {
290       e.target.openPopup();
291     });
292   });
293 });