diff --git a/lib/OpenLayers/Control/ModifyFeature.js b/lib/OpenLayers/Control/ModifyFeature.js index dbf2348271..31d968cbb5 100644 --- a/lib/OpenLayers/Control/ModifyFeature.js +++ b/lib/OpenLayers/Control/ModifyFeature.js @@ -368,6 +368,11 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, { this.dragControl.activate(); this.onModificationStart(this.feature); } + // keep track of geometry modifications + var modified = feature.modified; + if (feature.geometry && !(modified && modified.geometry)) { + this._originalGeometry = feature.geometry.clone(); + } }, /** @@ -539,6 +544,13 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, { if(this.feature.state != OpenLayers.State.INSERT && this.feature.state != OpenLayers.State.DELETE) { this.feature.state = OpenLayers.State.UPDATE; + if (this.modified && this._originalGeometry) { + var feature = this.feature; + feature.modified = OpenLayers.Util.extend(feature.modified, { + geometry: this._originalGeometry + }); + delete this._originalGeometry; + } } }, diff --git a/lib/OpenLayers/Feature/Vector.js b/lib/OpenLayers/Feature/Vector.js index d7bbc6ba8f..905e146f40 100644 --- a/lib/OpenLayers/Feature/Vector.js +++ b/lib/OpenLayers/Feature/Vector.js @@ -81,6 +81,42 @@ OpenLayers.Feature.Vector = OpenLayers.Class(OpenLayers.Feature, { * {String} rendering intent currently being used */ renderIntent: "default", + + /** + * APIProperty: modified + * {Object} An object with the originals of the geometry and attributes of + * the feature, if they were changed. Currently this property is only read + * by , and written by + * , which sets the geometry property. + * Applications can set the originals of modified attributes in the + * attributes property. Note that applications have to check if this + * object and the attributes property is already created before using it. + * After a change made with ModifyFeature, this object could look like + * + * (code) + * { + * geometry: >Object + * } + * (end) + * + * When an application has made changes to feature attributes, it could + * have set the attributes to something like this: + * + * (code) + * { + * attributes: { + * myAttribute: "original" + * } + * } + * (end) + * + * Note that only checks for truthy values in + * *modified.geometry* and the attribute names in *modified.attributes*, + * but it is recommended to set the original values (and not just true) as + * attribute value, so applications could use this information to undo + * changes. + */ + modified: null, /** * Constructor: OpenLayers.Feature.Vector diff --git a/lib/OpenLayers/Format/WFST/v1.js b/lib/OpenLayers/Format/WFST/v1.js index f810cc03d6..118888b463 100644 --- a/lib/OpenLayers/Format/WFST/v1.js +++ b/lib/OpenLayers/Format/WFST/v1.js @@ -172,9 +172,24 @@ OpenLayers.Format.WFST.v1 = OpenLayers.Class(OpenLayers.Format.XML, { * type - insert, update, or delete. * * Parameters: - * features - {Array()} A list of features. + * features - {Array()} A list of features. See + * below for a more detailed description of the influence of the + * feature's *modified* property. * options - {Object} * + * feature.modified rules: + * If a feature has a modified property set, the following checks will be + * made before a feature's geometry or attribute is included in an Update + * transaction: + * - *modified* is not set at all: The geometry and all attributes will be + * included. + * - *modified.geometry* is truthy: The geometry will be + * included. If *modified.attributes* is not set, all attributes will + * be included. + * - *modified.attributes* is set: Only the attributes with a truthy value + * in *modified.attributes* will be included. If *modified.geometry* + * is not set, the geometry will not be included. + * * Returns: * {String} A serialized WFS transaction. */ @@ -276,7 +291,8 @@ OpenLayers.Format.WFST.v1 = OpenLayers.Class(OpenLayers.Format.XML, { } // add in geometry - if (this.geometryName !== null) { + var modified = feature.modified; + if (this.geometryName !== null && (!modified || modified.geometry)) { this.srsName = this.getSrsName(feature); this.writeNode( "Property", {name: this.geometryName, value: feature.geometry}, node @@ -285,7 +301,9 @@ OpenLayers.Format.WFST.v1 = OpenLayers.Class(OpenLayers.Format.XML, { // add in attributes for(var key in feature.attributes) { - if(feature.attributes[key] !== undefined) { + if(feature.attributes[key] !== undefined && + (!modified || !modified.attributes || + (modified.attributes && modified.attributes[key]))) { this.writeNode( "Property", {name: key, value: feature.attributes[key]}, node ); diff --git a/tests/Control/ModifyFeature.html b/tests/Control/ModifyFeature.html index a3259dd023..940e1b7799 100644 --- a/tests/Control/ModifyFeature.html +++ b/tests/Control/ModifyFeature.html @@ -736,8 +736,30 @@ map.destroy(); } - - + + function test_setFeatureState(t) { + t.plan(4); + var map = new OpenLayers.Map("map"); + var layer = new OpenLayers.Layer.Vector("vector", {isBaseLayer: true}); + map.addLayer(layer); + var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,2)); + layer.addFeatures([feature]); + var control = new OpenLayers.Control.ModifyFeature(layer, {standalone: true}); + map.addControl(control); + + control.selectFeature(feature); + var originalGeometry = feature.geometry; + + t.ok(control._originalGeometry, "original geometry stored for later use in setFeatureState"); + + feature.geometry = new OpenLayers.Geometry.Point(2,3); + control.modified = true; + control.setFeatureState(); + + t.eq(feature.state, OpenLayers.State.UPDATE, "feature state set to UPDATE"); + t.geom_eq(feature.modified.geometry, originalGeometry, "original geometry stored on the modified property"); + t.eq(control._originalGeometry, undefined, "original geometry deleted once it is set on the modified property"); + } diff --git a/tests/Format/WFST/v1.html b/tests/Format/WFST/v1.html index a65d795e53..6833a2b7ca 100644 --- a/tests/Format/WFST/v1.html +++ b/tests/Format/WFST/v1.html @@ -45,7 +45,7 @@ deleteFeature.state = OpenLayers.State.DELETE; deleteFeature.fid = "fid.37"; - t.plan(5); + t.plan(7); var snippets = { "GetFeature": {maxFeatures: 1, outputFormat: 'json'}, "Transaction": null, @@ -61,6 +61,19 @@ var got = format.writers["wfs"][snippet].apply(format, [arg]); t.xml_eq(got, expected, snippet + " request created correctly"); } + + updateFeature.modified = {geometry: updateFeature.geometry.clone()}; + updateFeature.geometry = new OpenLayers.Geometry.Point(2,3); + var expected = readXML("UpdateModified"); + var got = format.writers["wfs"]["Update"].apply(format, [updateFeature]); + t.xml_eq(got, expected, "Update request for feature with modified geometry created correctly"); + + updateFeature.modified.attributes = {foo: "bar"}; + updateFeature.attributes.foo = "baz"; + delete updateFeature.modified.geometry; + var expected = readXML("UpdateModifiedNoGeometry"); + var got = format.writers["wfs"]["Update"].apply(format, [updateFeature]); + t.xml_eq(got, expected, "Update request for feature with no modified geometry but modified attributes created correctly"); } function test_writeNative(t) { @@ -264,6 +277,39 @@ --> +
+