Generate proper descriptions for notes
[rails.git] / app / assets / javascripts / notes.js.erb
1 function addNoteLayer(map, notesUrl, newNoteControls, newNoteForm, minZoom) {
2   var newNotes;
3
4   var saveNewNotes = function (o) {
5     var layer = o.object;
6     newNotes = layer.getFeaturesByAttribute("status", "new")
7     layer.removeFeatures(newNotes, { silent: true });
8   };
9
10   var restoreNewNotes = function (o) {
11     var layer = o.object;
12     layer.addFeatures(newNotes);
13     newNotes = undefined;
14   };
15
16   var describeNote = function (n) {
17     var description = "<h2>Note " + n.id + "</h2>";
18
19     n.comments.forEach(function (c) {
20       description += "<p><small class='deemphasize'>" + c.action + " by ";
21       description += c.user + " at " + c.date + "</small><br/>" + c.text + "</p>";
22     });
23
24     return description;
25   }
26
27   var noteSelected = function (o) {
28     var feature = o.feature;
29     var location = feature.geometry.getBounds().getCenterLonLat();
30     var content;
31     var close;
32
33     if (feature.attributes.status === "new") {
34       var form = newNoteForm.clone();
35       form.removeClass("hidden");
36       content = form.html();
37       close = false;
38     } else {
39       content = describeNote(feature.attributes);
40       close = true;
41     };
42
43     feature.popup = new OpenLayers.Popup.FramedCloud(
44       feature.attributes.id, location, null, content, null, close,
45       function (e) { map.noteSelector.unselect(feature) }
46     );
47
48     map.addPopup(feature.popup);
49     // feature.popup.show();
50
51     $(feature.popup.contentDiv).find("textarea").autoGrow();
52
53     $(feature.popup.contentDiv).find("input#note-submit").click(function (e) {
54       var location = unproj(feature.geometry.getBounds().getCenterLonLat());
55       var form = $(e.target).parents("form").first();
56
57       $.ajax(form.prop("action"), {
58         type: form.prop("method"),
59         data: {
60           lon: location.lon,
61           lat: location.lat,
62           text: form.find("textarea#comment").val()
63         },
64         success: function (data) {
65           map.noteSelector.unselect(feature);
66
67           feature.attributes.status = "open";
68           feature.attributes.id = data;
69
70           map.noteLayer.drawFeature(feature);
71
72           map.noteMover.deactivate();
73         }
74       });
75
76       e.preventDefault();
77     });
78
79     $(feature.popup.contentDiv).find("input#note-cancel").click(function (e) {
80       feature.attributes.status = "cancelled";
81
82       map.noteSelector.unselect(feature);
83       map.noteLayer.removeFeatures(feature);
84
85       feature.destroy();
86
87       map.noteMover.deactivate();
88
89       e.preventDefault();
90     });
91
92     feature.popup.updateSize();
93   };
94
95   var noteUnselected = function (o) {
96     var feature = o.feature;
97
98     map.removePopup(feature.popup);
99
100     delete feature.popup;
101   };
102
103   var allowNoteReports = function () { 
104     if (map.getZoom() > minZoom) {
105       newNoteControls.show();
106     } else {
107       newNoteControls.hide();
108     }
109   };
110
111   var addNote = function () {
112     var lonlat = map.getCenter();
113     var layer = map.noteLayer;
114     var geometry = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat);
115     var feature = new OpenLayers.Feature.Vector(geometry, {
116       status: "new"
117     });
118
119     layer.addFeatures(feature);
120     map.noteSelector.unselectAll();
121     map.noteSelector.select(feature);
122     map.noteMover.activate();
123     map.noteLayer.setVisibility(true);
124   };
125
126   map.noteLayer = new OpenLayers.Layer.Vector("Notes", {
127     visibility: false,
128     displayInLayerSwitcher: false,
129     projection: new OpenLayers.Projection("EPSG:4326"),
130     styleMap: new OpenLayers.StyleMap(new OpenLayers.Style({
131       graphicWidth: 22,
132       graphicHeight: 22,
133       graphicOpacity: 0.7,
134       graphicXOffset: -11,
135       graphicYOffset: -11
136     }, {
137       rules: [
138         new OpenLayers.Rule({
139           filter: new OpenLayers.Filter.Comparison({
140             type: OpenLayers.Filter.Comparison.EQUAL_TO,
141             property: "status",
142             value: "new"
143           }),
144           symbolizer: {
145             externalGraphic: "<%= image_path 'new_note_marker.png' %>"
146           }
147         }),
148         new OpenLayers.Rule({
149           filter: new OpenLayers.Filter.Comparison({
150             type: OpenLayers.Filter.Comparison.EQUAL_TO,
151             property: "status",
152             value: "open"
153           }),
154           symbolizer: {
155             externalGraphic: "<%= image_path 'open_note_marker.png' %>"
156           }
157         }),
158         new OpenLayers.Rule({
159           filter: new OpenLayers.Filter.Comparison({
160             type: OpenLayers.Filter.Comparison.EQUAL_TO,
161             property: "status",
162             value: "closed"
163           }),
164           symbolizer: {
165             externalGraphic: "<%= image_path 'closed_note_marker.png' %>"
166           }
167         })
168       ]
169     })),
170     strategies: [
171       new OpenLayers.Strategy.BBOX()
172     ],
173     protocol: new OpenLayers.Protocol.HTTP({
174       url: notesUrl,
175       format: new OpenLayers.Format.GeoJSON()
176     })
177   });
178
179   map.noteLayer.events.register("beforefeaturesremoved", map, saveNewNotes);
180   map.noteLayer.events.register("featuresremoved", map, restoreNewNotes);
181   map.noteLayer.events.register("featureselected", map, noteSelected);
182   map.noteLayer.events.register("featureunselected", map, noteUnselected);
183
184   map.addLayer(map.noteLayer);
185
186   map.noteSelector = new OpenLayers.Control.SelectFeature(map.noteLayer, {
187     autoActivate: true
188   });
189
190   map.addControl(map.noteSelector);
191
192   map.noteMover = new OpenLayers.Control.DragFeature(map.noteLayer, {
193     onDrag: function (feature, pixel) {
194       feature.popup.lonlat = feature.geometry.getBounds().getCenterLonLat();
195       feature.popup.updatePosition();
196     },
197     featureCallbacks: {
198       over: function (feature) {
199         if (feature.attributes.status === "new") {
200           map.noteMover.overFeature.apply(map.noteMover, [feature]);
201         }
202       }
203     }
204   });
205
206   map.addControl(map.noteMover);
207
208   newNoteControls.click(addNote);
209
210   map.events.register("zoomend", map, allowNoteReports);
211
212   return map.noteLayer;
213 }