diff --git a/css/app.css b/css/app.css
index cdadef524..b977ebeea 100644
--- a/css/app.css
+++ b/css/app.css
@@ -227,3 +227,35 @@ button small {
position:fixed;
left:0px; right:0px; top:0px; bottom:0px;
}
+
+.commit-pane h2 {
+ font: bold 24px/40px 'Helvetica';
+}
+
+.commit-pane h3 small.count {
+ font: normal 12px/40px 'Helvetica';
+ border-radius:20px;
+ padding:5px;
+ background:#555;
+ margin-left:10px;
+ color:#fff;
+}
+
+.commit-pane h3 {
+ font: bold 18px/30px 'Helvetica';
+}
+
+.commit-pane ul {
+ border-bottom:1px solid #ccc;
+ background:#fff;
+}
+
+.commit-pane li {
+ border-top:1px solid #ccc;
+ padding:2px 10px;
+}
+
+.commit-pane .changeset-comment {
+ width:630px;
+ font-size:100%;
+}
diff --git a/index.html b/index.html
index 02261e971..da63fc058 100644
--- a/index.html
+++ b/index.html
@@ -25,6 +25,7 @@
+
diff --git a/js/iD/Connection.js b/js/iD/Connection.js
index 9170f39f3..3df75fe6f 100644
--- a/js/iD/Connection.js
+++ b/js/iD/Connection.js
@@ -97,12 +97,12 @@ iD.Connection = function() {
return oauth.authenticated();
}
- function createChangeset(changes) {
+ function putChangeset(changes, comment, callback) {
oauth.xhr({
method: 'PUT',
path: '/api/0.6/changeset/create',
options: { header: { 'Content-Type': 'text/xml' } },
- content: iD.format.XML.changeset()
+ content: iD.format.XML.changeset(comment)
},
function (changeset_id) {
oauth.xhr({
@@ -115,7 +115,7 @@ iD.Connection = function() {
method: 'PUT',
path: '/api/0.6/changeset/' + changeset_id + '/close'
}, function () {
- alert('saved! ' + apiURL.replace('/api/0.6', '/browse') + '/changeset/' + changeset_id);
+ callback(changeset_id);
});
});
});
@@ -155,7 +155,7 @@ iD.Connection = function() {
connection.userDetails = userDetails;
connection.authenticate = authenticate;
connection.authenticated = authenticated;
- connection.createChangeset = createChangeset;
+ connection.putChangeset = putChangeset;
connection.objectData = objectData;
connection.apiURL = apiURL;
diff --git a/js/iD/id.js b/js/iD/id.js
index b870ba419..85b807aed 100644
--- a/js/iD/id.js
+++ b/js/iD/id.js
@@ -11,21 +11,17 @@ var iD = function(container) {
container = d3.select(container);
var m = container.append('div')
- .attr('id', 'map');
+ .attr('id', 'map'),
+ connection = iD.Connection()
+ .url('http://api06.dev.openstreetmap.org'),
+ map = iD.Map(m.node(), connection),
+ controller = iD.Controller(map),
+ bar = container.append('div')
+ .attr('id', 'bar');
- var connection = iD.Connection()
- .url('http://api06.dev.openstreetmap.org');
-
- var map = iD.Map(m.node(), connection);
-
- var controller = iD.Controller(map);
-
- var bar = container.append('div')
- .attr('id', 'bar');
-
- var buttons = bar.selectAll('button')
+ var buttons = bar.selectAll('button.add-button')
.data([iD.modes.AddPlace, iD.modes.AddRoad, iD.modes.AddArea])
- .enter().append('button')
+ .enter().append('button').attr('class', 'add-button')
.text(function (mode) { return mode.title; })
.on('click', function (mode) { controller.enter(mode); });
@@ -34,30 +30,26 @@ var iD = function(container) {
});
bar.append('button')
- .attr('id', 'undo')
- .attr('class', 'mini')
+ .attr({ id: 'undo', 'class': 'mini' })
.property('disabled', true)
.html('←')
.on('click', map.undo);
bar.append('button')
- .attr('id', 'redo')
- .attr('class', 'mini')
+ .attr({ id: 'redo', 'class': 'mini' })
.property('disabled', true)
.html('→')
.on('click', map.redo);
bar.append('input')
- .attr('type', 'text')
- .attr('placeholder', 'find a place')
- .attr('id', 'geocode-location')
+ .attr({ type: 'text', placeholder: 'find a place', id: 'geocode-location' })
.on('keydown', function () {
if (d3.event.keyCode !== 13) return;
d3.event.preventDefault();
var val = d3.select('#geocode-location').node().value;
- var scr = document.body.appendChild(document.createElement('script'));
- scr.src = 'http://api.tiles.mapbox.com/v3/mapbox/geocode/' +
- encodeURIComponent(val) + '.jsonp?callback=grid';
+ d3.select(document.body).append('script')
+ .attr('src', 'http://api.tiles.mapbox.com/v3/mapbox/geocode/' +
+ encodeURIComponent(val) + '.jsonp?callback=grid');
});
window.grid = function(resp) {
@@ -77,7 +69,21 @@ var iD = function(container) {
.html("Save")
.on('click', function() {
connection.authenticate(function() {
- map.commit();
+ var commitpane = iD.Commit();
+ var shaded = d3.select(document.body)
+ .append('div').attr('class', 'shaded');
+ var modal = shaded.append('div')
+ .attr('class', 'modal commit-pane')
+ .datum(map.history.changes());
+ modal.call(commitpane);
+ commitpane.on('cancel', function() {
+ shaded.remove();
+ });
+ commitpane.on('save', function(e) {
+ connection.putChangeset(map.history.changes(), e.comment, function() {
+ shaded.remove();
+ });
+ });
});
});
diff --git a/js/iD/renderer/Map.js b/js/iD/renderer/Map.js
index 84170deef..03a372d72 100644
--- a/js/iD/renderer/Map.js
+++ b/js/iD/renderer/Map.js
@@ -503,7 +503,7 @@ iD.Map = function(elem, connection) {
}
function commit() {
- connection.createChangeset(history.changes());
+ connection.putChangeset(history.changes());
}
map.download = download;
diff --git a/js/iD/ui/commit.js b/js/iD/ui/commit.js
new file mode 100644
index 000000000..b0b83853c
--- /dev/null
+++ b/js/iD/ui/commit.js
@@ -0,0 +1,53 @@
+iD.Commit = function() {
+ var event = d3.dispatch('cancel', 'save');
+
+ function commit(selection) {
+ var changes = selection.datum();
+ var header = selection.append('div').attr('class', 'header');
+ var body = selection.append('div').attr('class', 'body');
+
+ header.append('h2').text('Save Changes to OpenStreetMap');
+
+ var section = body.selectAll('div.section')
+ .data(['modify', 'delete', 'create'].filter(function(d) {
+ return changes[d].length;
+ }))
+ .enter()
+ .append('div').attr('class', 'section');
+
+ section.append('h3').text(String)
+ .append('small')
+ .attr('class', 'count')
+ .text(function(d) { return changes[d].length; });
+
+ var li = section.append('ul')
+ .selectAll('li')
+ .data(function(d) { return changes[d]; })
+ .enter()
+ .append('li');
+
+ li.append('strong').text(function(d) {
+ return d.type + ' ';
+ });
+ li.append('span').text(function(d) {
+ return iD.Util.friendlyName(d);
+ });
+
+ body.append('textarea')
+ .attr('class', 'changeset-comment')
+ .attr('placeholder', 'Brief Description');
+
+ body.append('button').text('Save')
+ .on('click', function() {
+ event.save({
+ comment: d3.select('textarea.changeset-comment').node().value
+ });
+ });
+ body.append('button').text('Cancel')
+ .on('click', function() {
+ event.cancel();
+ });
+ }
+
+ return d3.rebind(commit, event, 'on');
+};