Add note creation to the sidebar

This commit is contained in:
Aaron Lidman 2013-11-11 19:06:07 -08:00
parent 85282f5cdd
commit 1b19974b12
9 changed files with 169 additions and 213 deletions

View file

@ -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,

View 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;
}

View file

@ -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();
};

View file

@ -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();
});
});
}

View file

@ -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>

View file

@ -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>

View 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>

View file

@ -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"

View file

@ -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