diff --git a/index.html b/index.html
index 8486834a8..2839653b4 100644
--- a/index.html
+++ b/index.html
@@ -80,7 +80,7 @@
.setAPI('http://api06.dev.openstreetmap.org/api/0.6');
if (oauth.authenticated()) {
- oauth.xhr('GET', '/user/details', function(user_details) {
+ oauth.xhr({ method: 'GET', path: '/user/details' }, function(user_details) {
var u = user_details.getElementsByTagName('user')[0];
map.connection.user({
display_name: u.attributes.display_name.nodeValue,
@@ -93,6 +93,7 @@
d3.selectAll('button#save').on('click', function() {
oauth.authenticate();
+ map.commit();
});
d3.selectAll('button#place').on('click', function() {
diff --git a/js/iD/OAuth.js b/js/iD/OAuth.js
index 4fdfdf415..cb68e6405 100644
--- a/js/iD/OAuth.js
+++ b/js/iD/OAuth.js
@@ -1,4 +1,4 @@
-iD.OAuth = function() {
+iD.OAuth = function(map) {
var baseurl = 'http://api06.dev.openstreetmap.org',
oauth_secret = 'aMnOOCwExO2XYtRVWJ1bI9QOdqh1cay2UgpbhA6p',
oauth = {};
@@ -20,14 +20,15 @@ iD.OAuth = function() {
localStorage.oauth_token_secret;
};
- oauth.xhr = function(method, path, callback) {
+ oauth.xhr = function(options, callback) {
o = timenonce(o);
- var url = baseurl + path;
+ var url = baseurl + options.path;
var oauth_token_secret = localStorage.oauth_token_secret;
o.oauth_signature = ohauth.signature(oauth_secret, oauth_token_secret,
- ohauth.baseString(method, url, o));
- ohauth.xhr(method, url, o, null, {}, function(xhr) {
+ ohauth.baseString(options.method, url, o));
+ ohauth.xhr(options.method, url, o, options.content, options.options, function(xhr) {
if (xhr.responseXML) callback(xhr.responseXML);
+ else callback(xhr.response);
});
};
@@ -80,5 +81,7 @@ iD.OAuth = function() {
return oauth;
};
+ map.oauth = oauth;
+
return oauth;
};
diff --git a/js/iD/actions/actions.js b/js/iD/actions/actions.js
index 604bdad3d..3aec89ce9 100644
--- a/js/iD/actions/actions.js
+++ b/js/iD/actions/actions.js
@@ -13,7 +13,7 @@ iD.actions._node = function(ll) {
lon: ll[0],
id: iD.Util.id('node'),
tags: {}
- });
+ }, {});
};
iD.actions.AddPlace = {
diff --git a/js/iD/format/XML.js b/js/iD/format/XML.js
index e63592c0e..4b545fc29 100644
--- a/js/iD/format/XML.js
+++ b/js/iD/format/XML.js
@@ -1,7 +1,12 @@
iD.format.XML = {
mapping: function(entity) {
- if (this.mappings[entity.type]) {
- return this.mappings[entity.type](entity);
+ if (iD.format.XML.mappings[entity.type]) {
+ return iD.format.XML.mappings[entity.type](entity);
+ }
+ },
+ rep: function(entity) {
+ if (iD.format.XML.reps[entity.type]) {
+ return iD.format.XML.reps[entity.type](entity);
}
},
decode: function(s) {
@@ -13,7 +18,7 @@ iD.format.XML = {
osm: {
changeset: {
tag: [
- { '@k': 'created_by', '@v': 'iD' },
+ { '@k': 'created_by', '@v': 'iD 0.0.0' },
{ '@k': 'comment', '@v': comment || '' }
],
'@version': 0.3,
@@ -22,45 +27,62 @@ iD.format.XML = {
}
}));
},
- osmChange: function() {
+ osmChange: function(userid, changeset, created) {
return (new XMLSerializer()).serializeToString(
JXON.unbuild({
osmChange: {
'@version': 0.3,
- '@generator': 'iD'
+ '@generator': 'iD',
+ // TODO: copy elements first
+ 'create': created.map(function(c) {
+ var x = Object.create(c);
+ x.changeset = changeset;
+ return x;
+ }).map(iD.format.XML.rep)
}
}));
},
+ reps: {
+ node: function(entity) {
+ var r = {
+ node: {
+ '@id': entity.id.replace('n', ''),
+ '@lat': entity.lat, '@lon': entity.lon,
+ tag: _.map(entity.tags, function(k, v) {
+ return { keyAttributes: { k: k, v: v } };
+ })
+ }
+ };
+ if (entity.changeset) r.node['@changeset'] = entity.changeset;
+ return r;
+ },
+ way: function(entity) {
+ var r = {
+ way: {
+ '@id': entity.id.replace('w', ''),
+ nd: entity.nodes.map(function(e) {
+ return { keyAttributes: { ref: e.id } };
+ }),
+ tag: _.map(entity.tags, function(k, v) {
+ return {
+ keyAttributes: { k: k, v: v }
+ };
+ })
+ }
+ };
+ if (entity.changeset) r.way['@changeset'] = entity.changeset;
+ return r;
+ }
+ },
mappings: {
node: function(entity) {
return iD.format.XML.decode((new XMLSerializer()).serializeToString(
- JXON.unbuild({
- node: {
- '@id': entity.id,
- '@lat': entity.lat, '@lon': entity.lon,
- tag: _.map(entity.tags, function(k, v) {
- return { keyAttributes: { k: k, v: v } };
- })
- }
- })
+ JXON.unbuild(iD.format.XML.reps.node(entity))
));
},
way: function(entity) {
- return iD.format.XML.decode(
- (new XMLSerializer()).serializeToString(
- JXON.unbuild({
- way: {
- '@id': entity.id,
- nd: entity.nodes.map(function(e) {
- return { keyAttributes: { ref: e.id } };
- }),
- tag: _.map(entity.tags, function(k, v) {
- return {
- keyAttributes: { k: k, v: v }
- };
- })
- }
- })));
+ return iD.format.XML.decode((new XMLSerializer()).serializeToString(
+ JXON.unbuild(iD.format.XML.reps.way(entity))));
}
}
};
diff --git a/js/iD/renderer/Map.js b/js/iD/renderer/Map.js
index b8797c5b2..6e49bd871 100644
--- a/js/iD/renderer/Map.js
+++ b/js/iD/renderer/Map.js
@@ -539,6 +539,32 @@ iD.Map = function(elem) {
return map;
}
+ function commit() {
+ var modified = _.filter(history.graph().entities, function(e) {
+ return e.modified;
+ });
+ var userid = connection.user().id;
+ map.oauth.xhr({
+ method: 'PUT',
+ path: '/changeset/create',
+ options: { header: { 'Content-Type': 'text/xml' } },
+ content: iD.format.XML.changeset() }, function(changeset_id) {
+ map.oauth.xhr({
+ method: 'POST',
+ path: '/changeset/' + changeset_id + '/upload',
+ options: { header: { 'Content-Type': 'text/xml' } },
+ content: iD.format.XML.osmChange(userid, changeset_id, modified)
+ }, function() {
+ map.oauth.xhr({
+ method: 'PUT',
+ path: '/changeset/' + changeset_id + '/close'
+ }, function() {
+ alert('saved!');
+ });
+ });
+ });
+ }
+
map.handleDrag = handleDrag;
map.download = download;
@@ -570,6 +596,8 @@ iD.Map = function(elem) {
map.redraw = redraw;
+ map.commit = commit;
+
setSize({ width: parent.node().offsetWidth, height: parent.node().offsetHeight });
hideInspector();
redraw();