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