]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/index/notes.js.erb
Add note selection to the sidebar
[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 noteLayer = map.noteLayer,
6       notes = {},
7       newNote;
8
9   var noteIcons = {
10     "new": L.icon({
11       iconUrl: "<%= image_path 'new_note_marker.png' %>",
12       iconSize: [25, 40],
13       iconAnchor: [12, 40]
14     }),
15     "open": L.icon({
16       iconUrl: "<%= image_path 'open_note_marker.png' %>",
17       iconSize: [25, 40],
18       iconAnchor: [12, 40]
19     }),
20     "closed": L.icon({
21       iconUrl: "<%= image_path 'closed_note_marker.png' %>",
22       iconSize: [25, 40],
23       iconAnchor: [12, 40]
24     })
25   };
26
27   map.on("layeradd", function (e) {
28     if (e.layer == noteLayer) {
29       loadNotes();
30       map.on("moveend", loadNotes);
31     }
32   }).on("layerremove", function (e) {
33     if (e.layer == noteLayer) {
34       map.off("moveend", loadNotes);
35       noteLayer.clearLayers();
36       notes = {};
37     }
38   }).on("popupclose", function (e) {
39     if (newNote && e.popup == newNote._popup) {
40       $(newNote).oneTime(10, "removenote", function () {
41         map.removeLayer(newNote);
42         newNote = null;
43       });
44     } 
45   })
46
47   noteLayer.on('click', function(e) {
48     OSM.route('/browse/note/' + e.layer.id);
49   })
50
51   function updateMarker(marker, feature) {
52     if (marker) {
53       marker.setIcon(noteIcons[feature.properties.status]);
54     } else {
55       marker = L.marker(feature.geometry.coordinates.reverse(), {
56         icon: noteIcons[feature.properties.status],
57         opacity: 0.9,
58         clickable: true
59       });
60       marker.id = feature.properties.id;
61       marker.addTo(noteLayer);
62     }
63     return marker;
64   }
65
66   noteLayer.getLayerId = function(marker) {
67     return marker.id;
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.toBBoxString();
78
79       if (noteLoader) noteLoader.abort();
80
81       noteLoader = $.ajax({
82         url: url,
83         success: success
84       });
85     }
86
87     function success(json) {
88       var oldNotes = notes;
89       notes = {};
90       json.features.forEach(updateMarkers);
91
92       function updateMarkers(feature) {
93         var marker = oldNotes[feature.properties.id];
94         delete oldNotes[feature.properties.id];
95         notes[feature.properties.id] = updateMarker(marker, feature);
96       }
97
98       for (id in oldNotes) {
99         noteLayer.removeLayer(oldNotes[id]);
100       }
101
102       noteLoader = null;
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, -40),
114       autoPanPadding: new L.Point(60, 40)
115     };
116   }
117
118   function createPopupContent(marker, properties, comment) {
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.resolve"));
126         $(form.comment).prop("disabled", true);
127       } else {
128         $(form.close).val(I18n.t("javascripts.notes.show.comment_and_resolve"));
129         $(form.comment).prop("disabled", false);
130       }
131     });
132
133     content.find("input[type=submit]").on("click", function (e) {
134       e.preventDefault();
135       var data = $(e.target).data();
136       updateNote(marker, e.target.form, data.method, data.url);
137     });
138
139     if (comment) {
140       content.find("textarea").val(comment).trigger("input");
141     }
142
143     return content[0];
144   }
145
146   var addNoteButton = $(".control-note .control-button");
147
148   function createNote(marker, form, url) {
149     var location = marker.getLatLng();
150
151     marker.options.draggable = false;
152     marker.dragging.disable();
153
154     $(form).find("input[type=submit]").prop("disabled", true);
155
156     $.ajax({
157       url: url,
158       type: "POST",
159       oauth: true,
160       data: {
161         lat: location.lat,
162         lon: location.lng,
163         text: $(form.text).val()
164       },
165       success: function(feature) {
166         noteCreated(feature, marker);
167       }
168     });
169
170     function noteCreated(feature, marker) {
171       $(marker._popup._content).find("textarea").val("");
172
173       notes[feature.properties.id] = updateMarker(false, feature);
174       OSM.route('/browse/note/' + feature.properties.id);
175       newNote = null;
176       marker.closePopup();
177       noteLayer.removeLayer(marker);
178       addNoteButton.removeClass("active");
179     }
180   }
181
182   function updateNote(marker, form, method, url) {
183     $(form).find("input[type=submit]").prop("disabled", true);
184
185     $.ajax({
186       url: url,
187       type: method,
188       oauth: true,
189       data: {
190         text: $(form.text).val()
191       },
192       success: function (feature) {
193         if (feature.properties.status == "hidden") {
194           noteLayer.removeLayer(marker);
195
196           delete notes[feature.properties.id];
197         } else {
198           var popupContent = createPopupContent(marker, feature.properties);
199
200           marker.setIcon(noteIcons[feature.properties.status]);
201           marker.setPopupContent(popupContent);
202         }
203       }
204     });
205   }
206
207   addNoteButton.on("click", function (e) {
208     e.preventDefault();
209     e.stopPropagation();
210
211     if (addNoteButton.hasClass("disabled")) return;
212     if (addNoteButton.hasClass("active")) return;
213
214     addNoteButton.addClass("active");
215
216     map.addLayer(noteLayer);
217
218     var mapSize = map.getSize();
219     var markerPosition;
220
221     if (mapSize.y > 800) {
222       markerPosition = [mapSize.x / 2, mapSize.y / 2];
223     } else if (mapSize.y > 400) {
224       markerPosition = [mapSize.x / 2, 400];
225     } else {
226       markerPosition = [mapSize.x / 2, mapSize.y];
227     }
228
229     newNote = L.marker(map.containerPointToLatLng(markerPosition), {
230       icon: noteIcons["new"],
231       opacity: 0.9,
232       draggable: true
233     });
234
235     var popupContent = $(JST["templates/notes/new"]());
236
237     popupContent.find("textarea").on("input", disableWhenBlank);
238
239     function disableWhenBlank(e) {
240       $(e.target.form.add).prop("disabled", $(e.target).val() === "");
241     }
242
243     popupContent.find("input[type=submit]").on("click", function (e) {
244       e.preventDefault();
245       createNote(newNote, e.target.form, '/api/0.6/notes.json');
246     });
247
248     newNote.addTo(noteLayer).bindPopup(popupContent[0], popupOptions()).openPopup();
249
250     newNote.on("remove", function (e) {
251       addNoteButton.removeClass("active");
252     }).on("dragstart", function (e) {
253       $(newNote).stopTime("removenote");
254     }).on("dragend", function (e) {
255       e.target.openPopup();
256     });
257   });
258 }