Avoid making the map scroll when adding a new note
[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
28   map.on("layeradd", function (e) {
29     if (e.layer == noteLayer) {
30       loadNotes();
31       map.on("moveend", loadNotes);
32     }
33   });
34
35   map.on("layerremove", function (e) {
36     if (e.layer == noteLayer) {
37       map.off("moveend", loadNotes);
38       noteLayer.clearLayers();
39     }
40   });
41
42   if (OSM.STATUS != 'api_offline' && OSM.STATUS != 'database_offline') {
43     map.layersControl.addOverlay(noteLayer, I18n.t("browse.start_rjs.notes_layer_name"));
44
45     if (params.notes) map.addLayer(noteLayer);
46   }
47
48   function updateMarker(marker, feature) {
49     var icon = noteIcons[feature.properties.status];
50     var popupContent = createPopupContent(marker, feature.properties);
51
52     if (marker)
53     {
54       marker.setIcon(noteIcons[feature.properties.status]);
55       marker._popup.setContent(popupContent);
56     }
57     else
58     {
59       marker = L.marker(feature.geometry.coordinates.reverse(), {
60         icon: icon,
61         opacity: 0.7
62       });
63
64       marker.addTo(noteLayer).bindPopup(popupContent, popupOptions());
65     }
66
67     return marker;
68   }
69
70   var noteLoader;
71
72   function loadNotes() {
73     var bounds = map.getBounds();
74     var size = bounds.getSize();
75
76     if (size <= OSM.MAX_NOTE_REQUEST_AREA) {
77       var url = "/api/" + OSM.API_VERSION + "/notes.json?bbox=" + bounds.toBBOX();
78
79       if (noteLoader) noteLoader.abort();
80
81       noteLoader = $.ajax({
82         url: url,
83         success: function (json) {
84           var oldNotes = notes;
85
86           notes = {};
87
88           json.features.forEach(function (feature) {
89             var marker = oldNotes[feature.properties.id];
90
91             delete oldNotes[feature.properties.id];
92
93             notes[feature.properties.id] = updateMarker(marker, feature);
94           });
95
96           for (id in oldNotes) {
97             noteLayer.removeLayer(oldNotes[id]);
98           }
99
100           noteLoader = null;
101         }
102       });
103     }
104   };
105
106   function popupOptions() {
107     var mapSize = map.getSize();
108
109     return { 
110       minWidth: 320,
111       maxWidth: mapSize.y * 1 / 3, 
112       maxHeight: mapSize.y * 2 / 3, 
113       offset: new L.Point(0, -3),
114       autoPanPadding: new L.Point(60, 40)
115     };
116   }
117
118   function createPopupContent(marker, properties) {
119     var content = $(JST["templates/notes/show"]({ note: properties }));
120
121     content.find("textarea").on("input", function (e) {
122       var form = e.target.form;
123
124       if ($(e.target).val() == "") {
125         $(form.close).val(I18n.t("javascripts.notes.show.close"));
126         $(form.comment).prop("disabled", true);
127       } else {
128         $(form.close).val(I18n.t("javascripts.notes.show.comment_and_close"));
129         $(form.comment).prop("disabled", false);
130       }
131     });
132
133     content.find("input[type=submit]").on("click", function (e) {
134       e.preventDefault();
135       updateNote(marker, e.target.form, $(e.target).data("url"));
136     });
137
138     return content[0];
139   }
140
141   function createNote(marker, form, url) {
142     var location = marker.getLatLng();
143
144     $(form).find("input[type=submit]").prop("disabled", true);
145
146     $.ajax({
147       url: url,
148       type: "POST",
149       data: {
150         lat: location.lat,
151         lon: location.lng,
152         text: $(form.text).val()
153       },
154       success: function (feature) {
155         notes[feature.properties.id] = updateMarker(marker, feature);
156
157         $(".leaflet-popup-close-button").off("click.close");
158       }
159     });
160   }
161
162   function updateNote(marker, form, url) {
163     $(form).find("input[type=submit]").prop("disabled", true);
164
165     $.ajax({
166       url: url,
167       type: "POST",
168       data: {
169         text: $(form.text).val()
170       },
171       success: function (feature) {
172         var popupContent = createPopupContent(marker, feature.properties);
173
174         marker.setIcon(noteIcons[feature.properties.status]);
175         marker._popup.setContent(popupContent);
176       }
177     });
178   }
179
180   $("#createnoteanchor").click(function (e) {
181     e.preventDefault();
182
183     if ($(e.target).hasClass("disabled")) return;
184
185     map.addLayer(noteLayer);
186
187     var mapSize = map.getSize();
188     var markerPosition;
189
190     if (mapSize.y > 800)
191     {
192       markerPosition = [mapSize.x / 2, mapSize.y / 2];
193     }
194     else if (mapSize.y > 400)
195     {
196       markerPosition = [mapSize.x / 2, 400];
197     }
198     else
199     {
200       markerPosition = [mapSize.x / 2, mapSize.y];
201     }
202
203     var marker = L.marker(map.containerPointToLatLng(markerPosition), {
204       icon: noteIcons["new"],
205       opacity: 0.7,
206       draggable: true
207     });
208
209     var popupContent = $(JST["templates/notes/new"]({ create_url: $(e.target).attr("href") }));
210
211     popupContent.find("input[type=submit]").on("click", function (e) {
212       e.preventDefault();
213       createNote(marker, e.target.form, $(e.target).data("url"));
214     });
215
216     marker.addTo(noteLayer).bindPopup(popupContent[0], popupOptions()).openPopup();
217
218     $(".leaflet-popup-close-button").on("click.close", function (e) {
219       map.removeLayer(marker);
220     });
221
222     marker.on("dragend", function (e) {
223       e.target.openPopup();
224     });
225   });
226 });