Rework notes UI using leaflet
This commit is contained in:
parent
78f608b114
commit
de78176e04
8 changed files with 152 additions and 230 deletions
|
@ -45,12 +45,11 @@ $(document).ready(function () {
|
|||
var centre = bbox.getCenter();
|
||||
updatelinks(centre.lon, centre.lat, 16, null, params.minlon, params.minlat, params.maxlon, params.maxlat);
|
||||
} else if (params.type == "note") {
|
||||
var centre = new OpenLayers.LonLat(params.lon, params.lat);
|
||||
map.setView([params.lat, params.lon], 16);
|
||||
|
||||
setMapCenter(centre, 16);
|
||||
addMarkerToMap(centre);
|
||||
L.marker([params.lat, params.lon], { icon: getUserIcon() }).addTo(map);
|
||||
|
||||
var bbox = unproj(map.getExtent());
|
||||
var bbox = map.getBounds();
|
||||
|
||||
$("#loading").hide();
|
||||
$("#browse_map .geolink").show();
|
||||
|
@ -59,7 +58,9 @@ $(document).ready(function () {
|
|||
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 {
|
||||
$("#object_larger_map").hide();
|
||||
$("#object_edit").hide();
|
||||
|
|
|
@ -3,247 +3,184 @@
|
|||
|
||||
$(document).ready(function () {
|
||||
var params = OSM.mapParams();
|
||||
var newNotes;
|
||||
|
||||
function saveNewNotes(o) {
|
||||
var layer = o.object;
|
||||
newNotes = layer.getFeaturesByAttribute("status", "new")
|
||||
layer.removeFeatures(newNotes, { silent: true });
|
||||
var noteIcons = {
|
||||
"new": L.icon({
|
||||
iconUrl: "<%= image_path 'new_note_marker.png' %>",
|
||||
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) {
|
||||
var layer = o.object;
|
||||
layer.addFeatures(newNotes);
|
||||
newNotes = undefined;
|
||||
function updateMarker(marker, feature) {
|
||||
var icon = noteIcons[feature.properties.status];
|
||||
var popupContent = createPopupContent(marker, feature.properties);
|
||||
|
||||
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) {
|
||||
var location = unproj(feature.geometry.getBounds().getCenterLonLat());
|
||||
function loadNotes() {
|
||||
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"), {
|
||||
type: "POST",
|
||||
data: {
|
||||
lon: location.lon,
|
||||
lat: location.lat,
|
||||
text: $(form.text).val()
|
||||
},
|
||||
success: function (data) {
|
||||
map.noteSelector.unselect(feature);
|
||||
notes = {};
|
||||
|
||||
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) {
|
||||
var url = close ? feature.attributes.close_url : feature.attributes.comment_url;
|
||||
function createPopupContent(marker, properties) {
|
||||
var content = $(JST["templates/notes/show"]({ note: properties }));
|
||||
|
||||
$(form).find("input[type=submit]").prop("disabled", true);
|
||||
|
||||
$.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) {
|
||||
content.find("textarea").on("input", function (e) {
|
||||
var form = e.target.form;
|
||||
|
||||
if ($(e.target).val() == "") {
|
||||
$(form.close).val(I18n.t("javascripts.notes.show.close"));
|
||||
$(form.comment).prop("disabled", true);
|
||||
} else {
|
||||
$(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();
|
||||
|
||||
createNote(feature, e.target.form);
|
||||
updateNote(marker, e.target.form, $(e.target).data("url"));
|
||||
});
|
||||
|
||||
$(feature.popup.contentDiv).find("input#note-comment").click(function (e) {
|
||||
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();
|
||||
return content[0];
|
||||
}
|
||||
|
||||
function noteUnselected(o) {
|
||||
var feature = o.feature;
|
||||
function createNote(marker, form, url) {
|
||||
var location = marker.getLatLng();
|
||||
|
||||
map.removePopup(feature.popup);
|
||||
}
|
||||
$(form).find("input[type=submit]").prop("disabled", true);
|
||||
|
||||
function addNote() {
|
||||
var lonlat = map.getCenter();
|
||||
var layer = map.noteLayer;
|
||||
var geometry = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat);
|
||||
var feature = new OpenLayers.Feature.Vector(geometry, {
|
||||
status: "new"
|
||||
});
|
||||
|
||||
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();
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "POST",
|
||||
data: {
|
||||
lat: location.lat,
|
||||
lon: location.lng,
|
||||
text: $(form.text).val()
|
||||
},
|
||||
featureCallbacks: {
|
||||
over: function (feature) {
|
||||
if (feature.attributes.status === "new") {
|
||||
map.noteMover.overFeature.apply(map.noteMover, [feature]);
|
||||
}
|
||||
}
|
||||
success: function (feature) {
|
||||
notes[feature.properties.id] = updateMarker(marker, 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) {
|
||||
map.noteLayer.setVisibility(true);
|
||||
$.ajax({
|
||||
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) {
|
||||
map.noteLayer.setVisibility(true);
|
||||
|
||||
addNote();
|
||||
var popupContent = $(JST["templates/notes/new"]({ create_url: $(e.target).attr("href") }));
|
||||
|
||||
popupContent.find("input[type=submit]").on("click", function (e) {
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -109,8 +109,6 @@ function createMap(divName, options) {
|
|||
map.invalidateSize();
|
||||
});
|
||||
|
||||
$("#" + divName).trigger("initialised");
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
<div class="note">
|
||||
<p>
|
||||
<%- I18n.t('javascripts.notes.new.intro_1') %><br/>
|
||||
<%- I18n.t('javascripts.notes.new.intro_2') %>
|
||||
</p>
|
||||
<p><%- I18n.t('javascripts.notes.new.intro') %></p>
|
||||
<form action="#">
|
||||
<input type="hidden" name="lon">
|
||||
<input type="hidden" name="lat">
|
||||
<textarea name="text" cols="40" rows="10"></textarea>
|
||||
<br/>
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
<textarea name="text" cols="40" rows="5"></textarea>
|
||||
<br/>
|
||||
<div class="buttons">
|
||||
<input type="submit" name="close" value="<%- I18n.t('javascripts.notes.show.close') %>" id="note-close">
|
||||
<input type="submit" name="comment" value="<%- I18n.t('javascripts.notes.show.comment') %>" id="note-comment">
|
||||
<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') %>" data-url="<%- note.comment_url %>" disabled="1">
|
||||
</div>
|
||||
</form>
|
||||
<% } %>
|
||||
|
|
|
@ -1417,11 +1417,7 @@ abbr.geo {
|
|||
|
||||
/* Rules for the notes interface */
|
||||
|
||||
.note {
|
||||
width: 300px;
|
||||
|
||||
.buttons {
|
||||
margin-top: 5px;
|
||||
text-align: right;
|
||||
}
|
||||
.note .buttons {
|
||||
margin-top: 5px;
|
||||
text-align: right;
|
||||
}
|
||||
|
|
|
@ -2,12 +2,6 @@
|
|||
<%= javascript_include_tag "index" %>
|
||||
<% 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 %>
|
||||
<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 %>
|
||||
|
|
|
@ -2017,8 +2017,7 @@ en:
|
|||
createnote_zoom_alert: You must zoom in to add a note to the map
|
||||
notes:
|
||||
new:
|
||||
intro_1: Move the marker to the correct position and
|
||||
intro_2: "add your comment in the box below:"
|
||||
intro: "Move the marker to the correct position and add your comment in the box below:"
|
||||
add: Add Note
|
||||
show:
|
||||
title: Note %{id}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue