Add note creation to the sidebar
This commit is contained in:
parent
85282f5cdd
commit
1b19974b12
9 changed files with 169 additions and 213 deletions
|
@ -11,6 +11,7 @@
|
|||
//= require index/notes
|
||||
//= require index/history
|
||||
//= require index/note
|
||||
//= require index/new_note
|
||||
//= require router
|
||||
|
||||
$(document).ready(function () {
|
||||
|
@ -221,6 +222,7 @@ $(document).ready(function () {
|
|||
"/search": OSM.Search(map),
|
||||
"/export": OSM.Export(map),
|
||||
"/history": history,
|
||||
"/new_note": OSM.NewNote(map),
|
||||
"/user/:display_name/edits": history,
|
||||
"/browse/friends": history,
|
||||
"/browse/nearby": history,
|
||||
|
|
144
app/assets/javascripts/index/new_note.js.erb
Normal file
144
app/assets/javascripts/index/new_note.js.erb
Normal file
|
@ -0,0 +1,144 @@
|
|||
OSM.NewNote = function(map) {
|
||||
var noteLayer = map.noteLayer,
|
||||
content = $('#sidebar_content'),
|
||||
page = {},
|
||||
addNoteButton = $(".control-note .control-button"),
|
||||
newNote;
|
||||
|
||||
var noteIcons = {
|
||||
"new": L.icon({
|
||||
iconUrl: "<%= image_path 'new_note_marker.png' %>",
|
||||
iconSize: [25, 40],
|
||||
iconAnchor: [12, 40]
|
||||
}),
|
||||
"open": L.icon({
|
||||
iconUrl: "<%= image_path 'open_note_marker.png' %>",
|
||||
iconSize: [25, 40],
|
||||
iconAnchor: [12, 40]
|
||||
}),
|
||||
"closed": L.icon({
|
||||
iconUrl: "<%= image_path 'closed_note_marker.png' %>",
|
||||
iconSize: [25, 40],
|
||||
iconAnchor: [12, 40]
|
||||
})
|
||||
};
|
||||
|
||||
page.pushstate = page.popstate = function() {
|
||||
page.load();
|
||||
};
|
||||
|
||||
addNoteButton.on("click", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
OSM.route('/new_note');
|
||||
});
|
||||
|
||||
function createNote(marker, form, url) {
|
||||
var location = marker.getLatLng();
|
||||
|
||||
marker.options.draggable = false;
|
||||
marker.dragging.disable();
|
||||
|
||||
$(form).find("input[type=submit]").prop("disabled", true);
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "POST",
|
||||
oauth: true,
|
||||
data: {
|
||||
lat: location.lat,
|
||||
lon: location.lng,
|
||||
text: $(form.text).val()
|
||||
},
|
||||
success: function(feature) {
|
||||
noteCreated(feature, marker);
|
||||
}
|
||||
});
|
||||
|
||||
function noteCreated(feature, marker) {
|
||||
content.find("textarea").val("");
|
||||
updateMarker(feature);
|
||||
newNote = null;
|
||||
noteLayer.removeLayer(marker);
|
||||
addNoteButton.removeClass("active");
|
||||
OSM.route('/browse/note/' + feature.properties.id);
|
||||
}
|
||||
}
|
||||
|
||||
function updateMarker(feature) {
|
||||
marker = L.marker(feature.geometry.coordinates.reverse(), {
|
||||
icon: noteIcons[feature.properties.status],
|
||||
opacity: 0.9,
|
||||
clickable: true
|
||||
});
|
||||
marker.id = feature.properties.id;
|
||||
marker.addTo(noteLayer);
|
||||
return marker;
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
if (addNoteButton.hasClass("disabled")) return;
|
||||
if (addNoteButton.hasClass("active")) return;
|
||||
|
||||
addNoteButton.addClass("active");
|
||||
|
||||
map.addLayer(noteLayer);
|
||||
|
||||
var mapSize = map.getSize();
|
||||
var markerPosition;
|
||||
|
||||
if (mapSize.y > 800) {
|
||||
markerPosition = [mapSize.x / 2, mapSize.y / 2];
|
||||
} else if (mapSize.y > 400) {
|
||||
markerPosition = [mapSize.x / 2, 400];
|
||||
} else {
|
||||
markerPosition = [mapSize.x / 2, mapSize.y];
|
||||
}
|
||||
|
||||
newNote = L.marker(map.containerPointToLatLng(markerPosition), {
|
||||
icon: noteIcons["new"],
|
||||
opacity: 0.9,
|
||||
draggable: true
|
||||
});
|
||||
|
||||
newNote.addTo(noteLayer)
|
||||
|
||||
newNote.on("remove", function (e) {
|
||||
addNoteButton.removeClass("active");
|
||||
}).on("dragstart", function (e) {
|
||||
$(newNote).stopTime("removenote");
|
||||
}).on("dragend", function (e) {
|
||||
content.find("textarea").focus();
|
||||
});
|
||||
|
||||
content.find("textarea")
|
||||
.on("input", disableWhenBlank)
|
||||
.focus();
|
||||
|
||||
function disableWhenBlank(e) {
|
||||
$(e.target.form.add).prop("disabled", $(e.target).val() === "");
|
||||
}
|
||||
|
||||
content.find('input[type=submit]').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
createNote(newNote, e.target.form, '/api/0.6/notes.json');
|
||||
});
|
||||
}
|
||||
|
||||
page.load = function() {
|
||||
content.load(window.location.pathname + "?xhr=1", function(a, b, xhr) {
|
||||
if (xhr.getResponseHeader('X-Page-Title')) {
|
||||
document.title = xhr.getResponseHeader('X-Page-Title');
|
||||
}
|
||||
initialize();
|
||||
});
|
||||
}
|
||||
|
||||
page.unload = function() {
|
||||
noteLayer.removeLayer(newNote);
|
||||
addNoteButton.removeClass("active");
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
|
@ -1,6 +1,3 @@
|
|||
//= require templates/notes/show
|
||||
//= require templates/notes/new
|
||||
|
||||
OSM.Note = function(map) {
|
||||
var noteLayer = map.noteLayer,
|
||||
content = $('#sidebar_content'),
|
||||
|
@ -66,7 +63,7 @@ OSM.Note = function(map) {
|
|||
content.find("textarea").val('').trigger("input");
|
||||
}
|
||||
|
||||
page.pushstate = page.popstate = function(path) {
|
||||
page.pushstate = page.popstate = function() {
|
||||
page.load();
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
//= require templates/notes/show
|
||||
//= require templates/notes/new
|
||||
|
||||
function initializeNotes(map) {
|
||||
var noteLayer = map.noteLayer,
|
||||
notes = {},
|
||||
|
@ -102,157 +99,4 @@ function initializeNotes(map) {
|
|||
noteLoader = null;
|
||||
}
|
||||
};
|
||||
|
||||
function popupOptions() {
|
||||
var mapSize = map.getSize();
|
||||
|
||||
return {
|
||||
minWidth: 320,
|
||||
maxWidth: mapSize.y * 1 / 3,
|
||||
maxHeight: mapSize.y * 2 / 3,
|
||||
offset: new L.Point(0, -40),
|
||||
autoPanPadding: new L.Point(60, 40)
|
||||
};
|
||||
}
|
||||
|
||||
function createPopupContent(marker, properties, comment) {
|
||||
var content = $(JST["templates/notes/show"]({ note: properties }));
|
||||
|
||||
content.find("textarea").on("input", function (e) {
|
||||
var form = e.target.form;
|
||||
|
||||
if ($(e.target).val() == "") {
|
||||
$(form.close).val(I18n.t("javascripts.notes.show.resolve"));
|
||||
$(form.comment).prop("disabled", true);
|
||||
} else {
|
||||
$(form.close).val(I18n.t("javascripts.notes.show.comment_and_resolve"));
|
||||
$(form.comment).prop("disabled", false);
|
||||
}
|
||||
});
|
||||
|
||||
content.find("input[type=submit]").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
var data = $(e.target).data();
|
||||
updateNote(marker, e.target.form, data.method, data.url);
|
||||
});
|
||||
|
||||
if (comment) {
|
||||
content.find("textarea").val(comment).trigger("input");
|
||||
}
|
||||
|
||||
return content[0];
|
||||
}
|
||||
|
||||
var addNoteButton = $(".control-note .control-button");
|
||||
|
||||
function createNote(marker, form, url) {
|
||||
var location = marker.getLatLng();
|
||||
|
||||
marker.options.draggable = false;
|
||||
marker.dragging.disable();
|
||||
|
||||
$(form).find("input[type=submit]").prop("disabled", true);
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "POST",
|
||||
oauth: true,
|
||||
data: {
|
||||
lat: location.lat,
|
||||
lon: location.lng,
|
||||
text: $(form.text).val()
|
||||
},
|
||||
success: function(feature) {
|
||||
noteCreated(feature, marker);
|
||||
}
|
||||
});
|
||||
|
||||
function noteCreated(feature, marker) {
|
||||
$(marker._popup._content).find("textarea").val("");
|
||||
|
||||
notes[feature.properties.id] = updateMarker(false, feature);
|
||||
OSM.route('/browse/note/' + feature.properties.id);
|
||||
newNote = null;
|
||||
marker.closePopup();
|
||||
noteLayer.removeLayer(marker);
|
||||
addNoteButton.removeClass("active");
|
||||
}
|
||||
}
|
||||
|
||||
function updateNote(marker, form, method, url) {
|
||||
$(form).find("input[type=submit]").prop("disabled", true);
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: method,
|
||||
oauth: true,
|
||||
data: {
|
||||
text: $(form.text).val()
|
||||
},
|
||||
success: function (feature) {
|
||||
if (feature.properties.status == "hidden") {
|
||||
noteLayer.removeLayer(marker);
|
||||
|
||||
delete notes[feature.properties.id];
|
||||
} else {
|
||||
var popupContent = createPopupContent(marker, feature.properties);
|
||||
|
||||
marker.setIcon(noteIcons[feature.properties.status]);
|
||||
marker.setPopupContent(popupContent);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addNoteButton.on("click", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (addNoteButton.hasClass("disabled")) return;
|
||||
if (addNoteButton.hasClass("active")) return;
|
||||
|
||||
addNoteButton.addClass("active");
|
||||
|
||||
map.addLayer(noteLayer);
|
||||
|
||||
var mapSize = map.getSize();
|
||||
var markerPosition;
|
||||
|
||||
if (mapSize.y > 800) {
|
||||
markerPosition = [mapSize.x / 2, mapSize.y / 2];
|
||||
} else if (mapSize.y > 400) {
|
||||
markerPosition = [mapSize.x / 2, 400];
|
||||
} else {
|
||||
markerPosition = [mapSize.x / 2, mapSize.y];
|
||||
}
|
||||
|
||||
newNote = L.marker(map.containerPointToLatLng(markerPosition), {
|
||||
icon: noteIcons["new"],
|
||||
opacity: 0.9,
|
||||
draggable: true
|
||||
});
|
||||
|
||||
var popupContent = $(JST["templates/notes/new"]());
|
||||
|
||||
popupContent.find("textarea").on("input", disableWhenBlank);
|
||||
|
||||
function disableWhenBlank(e) {
|
||||
$(e.target.form.add).prop("disabled", $(e.target).val() === "");
|
||||
}
|
||||
|
||||
popupContent.find("input[type=submit]").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
createNote(newNote, e.target.form, '/api/0.6/notes.json');
|
||||
});
|
||||
|
||||
newNote.addTo(noteLayer).bindPopup(popupContent[0], popupOptions()).openPopup();
|
||||
|
||||
newNote.on("remove", function (e) {
|
||||
addNoteButton.removeClass("active");
|
||||
}).on("dragstart", function (e) {
|
||||
$(newNote).stopTime("removenote");
|
||||
}).on("dragend", function (e) {
|
||||
e.target.openPopup();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
<div class="note">
|
||||
<p><%- I18n.t('javascripts.notes.new.intro') %></p>
|
||||
<form action="#">
|
||||
<input type="hidden" name="lon">
|
||||
<input type="hidden" name="lat">
|
||||
<textarea class="comment" name="text" cols="40" rows="10"></textarea>
|
||||
<br/>
|
||||
<div class="buttons clearfix">
|
||||
<input type="submit" name="add" value="<%- I18n.t('javascripts.notes.new.add') %>" disabled="1">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
|
@ -1,41 +0,0 @@
|
|||
<div class="note">
|
||||
<a class="icon link permalink deemphasize" href="/browse/note/<%- note.id %>"><span><%- I18n.t('javascripts.notes.show.permalink', { id: note.id }) %></span></a>
|
||||
<% if (note.comments.some(function (comment) { return !comment.user })) { %>
|
||||
<small class="warning"><%- I18n.t('javascripts.notes.show.anonymous_warning') %></small>
|
||||
<% } %>
|
||||
<% note.comments.forEach(function (comment) { %>
|
||||
<div>
|
||||
<small class="deemphasize">
|
||||
<% if (comment.user) { %>
|
||||
<%= I18n.t('javascripts.notes.show.' + comment.action + '_by', {
|
||||
user: comment.user, user_url: comment.user_url,
|
||||
time: I18n.l("time.formats.long", comment.date)
|
||||
}) %>
|
||||
<% } else { %>
|
||||
<%- I18n.t('javascripts.notes.show.' + comment.action + '_by_anonymous', {
|
||||
time: I18n.l("time.formats.long", comment.date)
|
||||
}) %>
|
||||
<% } %>
|
||||
</small>
|
||||
<div class="comment_body"><%= comment.html %></div>
|
||||
</div>
|
||||
<% }) %>
|
||||
<% if (note.status == "open") { %>
|
||||
<form action="#">
|
||||
<textarea class="comment" name="text" cols="40" rows="5"></textarea>
|
||||
<div class="buttons clearfix">
|
||||
<input type="submit" name="hide" value="<%- I18n.t('javascripts.notes.show.hide') %>" class="hide_unless_moderator deemphasize" data-method="DELETE" data-url="<%- note.url %>">
|
||||
<input type="submit" name="close" value="<%- I18n.t('javascripts.notes.show.resolve') %>" class="hide_unless_logged_in" data-method="POST" data-url="<%- note.close_url %>">
|
||||
<input type="submit" name="comment" value="<%- I18n.t('javascripts.notes.show.comment') %>" data-method="POST" data-url="<%- note.comment_url %>" disabled="1">
|
||||
</div>
|
||||
</form>
|
||||
<% } else { %>
|
||||
<form action="#">
|
||||
<input type="hidden" name="text" value="">
|
||||
<div class="buttons clearfix">
|
||||
<input type="submit" name="hide" value="<%- I18n.t('javascripts.notes.show.hide') %>" class="hide_unless_moderator deemphasize" data-method="DELETE" data-url="<%- note.url %>">
|
||||
<input type="submit" name="reopen" value="<%- I18n.t('javascripts.notes.show.reactivate') %>" class="hide_unless_logged_in" data-method="POST" data-url="<%- note.reopen_url %>">
|
||||
</div>
|
||||
</form>
|
||||
<% } %>
|
||||
</div>
|
20
app/views/browse/new_note.html.erb
Normal file
20
app/views/browse/new_note.html.erb
Normal file
|
@ -0,0 +1,20 @@
|
|||
<% set_title("New Note") %>
|
||||
|
||||
<h2>
|
||||
<a class="geolink" href="<%= root_path %>"><span class="icon close"></span></a>
|
||||
<%= t "browse.note.new_note" %>
|
||||
</h2>
|
||||
|
||||
<div class="note browse-section">
|
||||
<p><%= t('javascripts.notes.new.intro') %></p>
|
||||
<form action="#">
|
||||
<input type="hidden" name="lon">
|
||||
<input type="hidden" name="lat">
|
||||
<br/>
|
||||
<textarea class="comment" name="text" cols="40" rows="10"></textarea>
|
||||
<br/>
|
||||
<div class="buttons clearfix">
|
||||
<input type="submit" name="add" value="<%= t('javascripts.notes.new.add') %>" disabled="1">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
|
@ -282,6 +282,7 @@ en:
|
|||
edit: "Edit way"
|
||||
note:
|
||||
title: "Note"
|
||||
new_note: "Add a note"
|
||||
open_title: "Unresolved note: %{note_name}"
|
||||
closed_title: "Resolved note: %{note_name}"
|
||||
opened: "Opened"
|
||||
|
|
|
@ -110,6 +110,7 @@ OpenStreetMap::Application.routes.draw do
|
|||
match '/browse/relation/:id/history' => 'browse#relation_history', :via => :get, :id => /\d+/
|
||||
match '/browse/changeset/:id' => 'browse#changeset', :via => :get, :as => :changeset, :id => /\d+/
|
||||
match '/browse/note/:id' => 'browse#note', :via => :get, :id => /\d+/, :as => "browse_note"
|
||||
match '/new_note' => 'browse#new_note', :via => :get
|
||||
match '/user/:display_name/edits' => 'changeset#list', :via => :get
|
||||
match '/user/:display_name/edits/feed' => 'changeset#feed', :via => :get, :defaults => { :format => :atom }
|
||||
match '/user/:display_name/notes' => 'notes#mine', :via => :get
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue