Rework notes UI using leaflet

This commit is contained in:
Tom Hughes 2012-12-01 17:46:26 +00:00
parent 78f608b114
commit de78176e04
8 changed files with 152 additions and 230 deletions

View file

@ -45,12 +45,11 @@ $(document).ready(function () {
var centre = bbox.getCenter(); var centre = bbox.getCenter();
updatelinks(centre.lon, centre.lat, 16, null, params.minlon, params.minlat, params.maxlon, params.maxlat); updatelinks(centre.lon, centre.lat, 16, null, params.minlon, params.minlat, params.maxlon, params.maxlat);
} else if (params.type == "note") { } else if (params.type == "note") {
var centre = new OpenLayers.LonLat(params.lon, params.lat); map.setView([params.lat, params.lon], 16);
setMapCenter(centre, 16); L.marker([params.lat, params.lon], { icon: getUserIcon() }).addTo(map);
addMarkerToMap(centre);
var bbox = unproj(map.getExtent()); var bbox = map.getBounds();
$("#loading").hide(); $("#loading").hide();
$("#browse_map .geolink").show(); $("#browse_map .geolink").show();
@ -59,7 +58,9 @@ $(document).ready(function () {
return remoteEditHandler(bbox); return remoteEditHandler(bbox);
}); });
updatelinks(centre.lon, centre.lat, 16, null, bbox.left, bbox.bottom, bbox.right, bbox.top) updatelinks(params.lon, params.lat, 16, null,
bbox.getWestLng(), bbox.getSouthLat(),
bbox.getEastLng(), bbox.getNorthLat());
} else { } else {
$("#object_larger_map").hide(); $("#object_larger_map").hide();
$("#object_edit").hide(); $("#object_edit").hide();

View file

@ -3,247 +3,184 @@
$(document).ready(function () { $(document).ready(function () {
var params = OSM.mapParams(); var params = OSM.mapParams();
var newNotes;
function saveNewNotes(o) { var noteIcons = {
var layer = o.object; "new": L.icon({
newNotes = layer.getFeaturesByAttribute("status", "new") iconUrl: "<%= image_path 'new_note_marker.png' %>",
layer.removeFeatures(newNotes, { silent: true }); iconSize: [22, 22],
iconAnchor: [11, 11]
}),
"open": L.icon({
iconUrl: "<%= image_path 'open_note_marker.png' %>",
iconSize: [22, 22],
iconAnchor: [11, 11]
}),
"closed": L.icon({
iconUrl: "<%= image_path 'closed_note_marker.png' %>",
iconSize: [22, 22],
iconAnchor: [11, 11]
})
};
var noteLayer = new L.LayerGroup();
var notes = {};
map.on("layeradd", function (e) {
if (e.layer == noteLayer) {
loadNotes();
map.on("moveend", loadNotes);
}
});
map.on("layerremove", function (e) {
if (e.layer == noteLayer) {
map.off("moveend", loadNotes);
noteLayer.clearLayers();
}
});
if (OSM.STATUS != 'api_offline' && OSM.STATUS != 'database_offline') {
map.layersControl.addOverlay(noteLayer, I18n.t("browse.start_rjs.notes_layer_name"));
if (params.notes) map.addLayer(noteLayer);
} }
function restoreNewNotes(o) { function updateMarker(marker, feature) {
var layer = o.object; var icon = noteIcons[feature.properties.status];
layer.addFeatures(newNotes); var popupContent = createPopupContent(marker, feature.properties);
newNotes = undefined;
if (marker)
{
marker.setIcon(noteIcons[feature.properties.status]);
marker._popup.setContent(popupContent);
}
else
{
marker = L.marker(feature.geometry.coordinates.reverse(), {
icon: icon,
opacity: 0.7
});
marker.addTo(noteLayer).bindPopup(popupContent);
}
return marker;
} }
function createNote(feature, form) { function loadNotes() {
var location = unproj(feature.geometry.getBounds().getCenterLonLat()); var bounds = map.getBounds();
var url = "/api/" + OSM.API_VERSION + "/notes.json?bbox=" + bounds.toBBOX();
$(form).find("input[type=submit]").prop("disabled", true); $.ajax({
url: url,
success: function (json) {
var oldNotes = notes;
$.ajax($("#createnoteanchor").attr("href"), { notes = {};
type: "POST",
data: {
lon: location.lon,
lat: location.lat,
text: $(form.text).val()
},
success: function (data) {
map.noteSelector.unselect(feature);
feature.attributes = data.properties; json.features.forEach(function (feature) {
var marker = oldNotes[feature.properties.id];
map.noteLayer.drawFeature(feature); delete oldNotes[feature.properties.id];
map.noteMover.deactivate(); notes[feature.properties.id] = updateMarker(marker, feature);
});
for (id in oldNotes) {
noteLayer.removeLayer(oldNotes[id]);
}
} }
}); });
} };
function updateNote(feature, form, close) { function createPopupContent(marker, properties) {
var url = close ? feature.attributes.close_url : feature.attributes.comment_url; var content = $(JST["templates/notes/show"]({ note: properties }));
$(form).find("input[type=submit]").prop("disabled", true); content.find("textarea").on("input", function (e) {
$.ajax(url, {
type: "POST",
data: {
text: $(form.text).val()
},
success: function (data) {
map.noteSelector.unselect(feature)
feature.attributes = data.properties;
map.noteSelector.select(feature)
}
});
}
function noteSelected(o) {
var feature = o.feature;
var location = feature.geometry.getBounds().getCenterLonLat();
var content;
var onClose;
if (feature.attributes.status === "new") {
content = JST["templates/notes/new"]();
onClose = function (e) {
feature.attributes.status = "cancelled";
map.noteSelector.unselect(feature);
map.noteLayer.removeFeatures(feature);
feature.destroy();
map.noteMover.deactivate();
};
} else {
content = JST["templates/notes/show"]({ note: feature.attributes });
onClose = function (e) {
map.noteSelector.unselect(feature)
};
};
feature.popup = new OpenLayers.Popup.FramedCloud(
feature.attributes.id, location, null, content, null, true, onClose
);
map.addPopup(feature.popup);
// feature.popup.show();
$(feature.popup.contentDiv).find("textarea").autoGrow();
$(feature.popup.contentDiv).find("textarea").on("input", function (e) {
var form = e.target.form; var form = e.target.form;
if ($(e.target).val() == "") { if ($(e.target).val() == "") {
$(form.close).val(I18n.t("javascripts.notes.show.close")); $(form.close).val(I18n.t("javascripts.notes.show.close"));
$(form.comment).prop("disabled", true);
} else { } else {
$(form.close).val(I18n.t("javascripts.notes.show.comment_and_close")); $(form.close).val(I18n.t("javascripts.notes.show.comment_and_close"));
$(form.comment).prop("disabled", false);
} }
}); });
$(feature.popup.contentDiv).find("input#note-add").click(function (e) { content.find("input[type=submit]").on("click", function (e) {
e.preventDefault(); e.preventDefault();
updateNote(marker, e.target.form, $(e.target).data("url"));
createNote(feature, e.target.form);
}); });
$(feature.popup.contentDiv).find("input#note-comment").click(function (e) { return content[0];
e.preventDefault();
updateNote(feature, e.target.form, false);
});
$(feature.popup.contentDiv).find("input#note-close").click(function (e) {
e.preventDefault();
updateNote(feature, e.target.form, true);
});
feature.popup.updateSize();
} }
function noteUnselected(o) { function createNote(marker, form, url) {
var feature = o.feature; var location = marker.getLatLng();
map.removePopup(feature.popup); $(form).find("input[type=submit]").prop("disabled", true);
}
function addNote() { $.ajax({
var lonlat = map.getCenter(); url: url,
var layer = map.noteLayer; type: "POST",
var geometry = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat); data: {
var feature = new OpenLayers.Feature.Vector(geometry, { lat: location.lat,
status: "new" lon: location.lng,
}); text: $(form.text).val()
layer.addFeatures(feature);
map.noteSelector.unselectAll();
map.noteSelector.select(feature);
map.noteMover.activate();
map.noteLayer.setVisibility(true);
}
$("#map").on("initialised", function () {
map.noteLayer = new OpenLayers.Layer.Vector("Notes", {
visibility: params.notes,
displayInLayerSwitcher: false,
projection: new OpenLayers.Projection("EPSG:4326"),
styleMap: new OpenLayers.StyleMap(new OpenLayers.Style({
graphicWidth: 22,
graphicHeight: 22,
graphicOpacity: 0.7,
graphicXOffset: -11,
graphicYOffset: -11
}, {
rules: [
new OpenLayers.Rule({
filter: new OpenLayers.Filter.Comparison({
type: OpenLayers.Filter.Comparison.EQUAL_TO,
property: "status",
value: "new"
}),
symbolizer: {
externalGraphic: "<%= image_path 'new_note_marker.png' %>"
}
}),
new OpenLayers.Rule({
filter: new OpenLayers.Filter.Comparison({
type: OpenLayers.Filter.Comparison.EQUAL_TO,
property: "status",
value: "open"
}),
symbolizer: {
externalGraphic: "<%= image_path 'open_note_marker.png' %>"
}
}),
new OpenLayers.Rule({
filter: new OpenLayers.Filter.Comparison({
type: OpenLayers.Filter.Comparison.EQUAL_TO,
property: "status",
value: "closed"
}),
symbolizer: {
externalGraphic: "<%= image_path 'closed_note_marker.png' %>"
}
})
]
})),
strategies: [
new OpenLayers.Strategy.BBOX()
],
protocol: new OpenLayers.Protocol.HTTP({
url: $("#show_notes").attr("href"),
format: new OpenLayers.Format.GeoJSON()
})
});
map.noteLayer.events.register("beforefeaturesremoved", map, saveNewNotes);
map.noteLayer.events.register("featuresremoved", map, restoreNewNotes);
map.noteLayer.events.register("featureselected", map, noteSelected);
map.noteLayer.events.register("featureunselected", map, noteUnselected);
map.addLayer(map.noteLayer);
map.noteSelector = new OpenLayers.Control.SelectFeature(map.noteLayer, {
autoActivate: true
});
map.addControl(map.noteSelector);
map.noteMover = new OpenLayers.Control.DragFeature(map.noteLayer, {
onDrag: function (feature, pixel) {
feature.popup.lonlat = feature.geometry.getBounds().getCenterLonLat();
feature.popup.updatePosition();
}, },
featureCallbacks: { success: function (feature) {
over: function (feature) { notes[feature.properties.id] = updateMarker(marker, feature);
if (feature.attributes.status === "new") {
map.noteMover.overFeature.apply(map.noteMover, [feature]); $(".leaflet-popup-close-button").off("click.close");
}
}
} }
}); });
}
map.addControl(map.noteMover); function updateNote(marker, form, url) {
$(form).find("input[type=submit]").prop("disabled", true);
$("#show_notes").click(function (e) { $.ajax({
map.noteLayer.setVisibility(true); url: url,
type: "POST",
data: {
text: $(form.text).val()
},
success: function (feature) {
var popupContent = createPopupContent(marker, feature.properties);
e.preventDefault(); marker.setIcon(noteIcons[feature.properties.status]);
marker._popup.setContent(popupContent);
}
});
}
$("#createnoteanchor").click(function (e) {
e.preventDefault();
map.addLayer(noteLayer);
var marker = L.marker(map.getCenter(), {
icon: noteIcons["new"],
opacity: 0.7,
draggable: true
}); });
$("#createnoteanchor").click(function (e) { var popupContent = $(JST["templates/notes/new"]({ create_url: $(e.target).attr("href") }));
map.noteLayer.setVisibility(true);
addNote();
popupContent.find("input[type=submit]").on("click", function (e) {
e.preventDefault(); e.preventDefault();
createNote(marker, e.target.form, $(e.target).data("url"));
});
marker.addTo(noteLayer).bindPopup(popupContent[0]).openPopup();
$(".leaflet-popup-close-button").on("click.close", function (e) {
map.removeLayer(marker);
});
marker.on("dragend", function (e) {
e.target.openPopup();
}); });
}); });
}); });

View file

@ -109,8 +109,6 @@ function createMap(divName, options) {
map.invalidateSize(); map.invalidateSize();
}); });
$("#" + divName).trigger("initialised");
return map; return map;
} }

View file

@ -1,15 +1,12 @@
<div class="note"> <div class="note">
<p> <p><%- I18n.t('javascripts.notes.new.intro') %></p>
<%- I18n.t('javascripts.notes.new.intro_1') %><br/>
<%- I18n.t('javascripts.notes.new.intro_2') %>
</p>
<form action="#"> <form action="#">
<input type="hidden" name="lon"> <input type="hidden" name="lon">
<input type="hidden" name="lat"> <input type="hidden" name="lat">
<textarea name="text" cols="40" rows="10"></textarea> <textarea name="text" cols="40" rows="10"></textarea>
<br/> <br/>
<div class="buttons"> <div class="buttons">
<input type="submit" name="add" value="<%- I18n.t('javascripts.notes.new.add') %>" id="note-add"> <input type="submit" name="add" value="<%- I18n.t('javascripts.notes.new.add') %>" data-url="<%- create_url %>">
</div> </div>
</form> </form>
</div> </div>

View file

@ -16,8 +16,8 @@
<textarea name="text" cols="40" rows="5"></textarea> <textarea name="text" cols="40" rows="5"></textarea>
<br/> <br/>
<div class="buttons"> <div class="buttons">
<input type="submit" name="close" value="<%- I18n.t('javascripts.notes.show.close') %>" id="note-close"> <input type="submit" name="close" value="<%- I18n.t('javascripts.notes.show.close') %>" data-url="<%- note.close_url %>">
<input type="submit" name="comment" value="<%- I18n.t('javascripts.notes.show.comment') %>" id="note-comment"> <input type="submit" name="comment" value="<%- I18n.t('javascripts.notes.show.comment') %>" data-url="<%- note.comment_url %>" disabled="1">
</div> </div>
</form> </form>
<% } %> <% } %>

View file

@ -1417,11 +1417,7 @@ abbr.geo {
/* Rules for the notes interface */ /* Rules for the notes interface */
.note { .note .buttons {
width: 300px; margin-top: 5px;
text-align: right;
.buttons {
margin-top: 5px;
text-align: right;
}
} }

View file

@ -2,12 +2,6 @@
<%= javascript_include_tag "index" %> <%= javascript_include_tag "index" %>
<% end %> <% end %>
<% unless STATUS == :api_offline or STATUS == :database_offline -%>
<% content_for :editmenu do -%>
<li><%= link_to t("browse.start_rjs.notes_layer_name"), notes_url(:format => :json), :id => "show_notes" %></li>
<% end -%>
<% end -%>
<% content_for :left_menu do %> <% content_for :left_menu do %>
<li><h4><%= link_to t("site.key.map_key"), {:action => :key}, :id => "open_map_key", :title => t("site.key.map_key_tooltip") %></h4></li> <li><h4><%= link_to t("site.key.map_key"), {:action => :key}, :id => "open_map_key", :title => t("site.key.map_key_tooltip") %></h4></li>
<% end %> <% end %>

View file

@ -2017,8 +2017,7 @@ en:
createnote_zoom_alert: You must zoom in to add a note to the map createnote_zoom_alert: You must zoom in to add a note to the map
notes: notes:
new: new:
intro_1: Move the marker to the correct position and intro: "Move the marker to the correct position and add your comment in the box below:"
intro_2: "add your comment in the box below:"
add: Add Note add: Add Note
show: show:
title: Note %{id} title: Note %{id}