Ticket #1699: patch-1699-r7944-C0.diff
| File patch-1699-r7944-C0.diff, 52.6 kB (added by elemoine, 2 years ago) |
|---|
-
build/license.txt
old new 52 52 * You may obtain a copy of the License at 53 53 * http://www.apache.org/licenses/LICENSE-2.0 54 54 */ 55 56 /** 57 * Contains portions of Gears <http://code.google.com/apis/gears/> 58 * 59 * Copyright 2007, Google Inc. 60 * 61 * Redistribution and use in source and binary forms, with or without 62 * modification, are permitted provided that the following conditions are met: 63 * 64 * 1. Redistributions of source code must retain the above copyright notice, 65 * this list of conditions and the following disclaimer. 66 * 2. Redistributions in binary form must reproduce the above copyright notice, 67 * this list of conditions and the following disclaimer in the documentation 68 * and/or other materials provided with the distribution. 69 * 3. Neither the name of Google Inc. nor the names of its contributors may be 70 * used to endorse or promote products derived from this software without 71 * specific prior written permission. 72 * 73 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 74 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 75 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 76 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 77 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 78 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 79 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 80 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 81 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 82 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 83 * 84 * Sets up google.gears.*, which is *the only* supported way to access Gears. 85 * 86 * Circumvent this file at your own risk! 87 * 88 * In the future, Gears may automatically define google.gears.* without this 89 * file. Gears may use these objects to transparently fix bugs and compatibility 90 * issues. Applications that use the code below will continue to work seamlessly 91 * when that happens. 92 */ -
tests/Protocol/SQL/Gears.html
old new 1 <html> 2 <head> 3 <script src="../../../lib/OpenLayers.js"></script> 4 <script type="text/javascript"> 5 6 function test_initialize(t) { 7 var protocol = new OpenLayers.Protocol.SQL.Gears(); 8 if (!protocol.supported()) { 9 t.plan(0); 10 return; 11 } 12 13 t.plan(5); 14 15 t.eq(protocol.CLASS_NAME, "OpenLayers.Protocol.SQL.Gears", 16 "ctor returns correct value"); 17 18 t.eq(protocol.jsonParser.CLASS_NAME, 19 "OpenLayers.Format.JSON", 20 "ctor creates a JSON parser"); 21 22 t.eq(protocol.wktParser.CLASS_NAME, 23 "OpenLayers.Format.WKT", 24 "ctor creates a WKT parser"); 25 26 var str = protocol.FID_PREFIX + "foo_bar"; 27 t.ok(str.match(protocol.fidRegExp), 28 "ctor creates correct regexp"); 29 30 t.ok(typeof protocol.db == "object", 31 "ctor creates a db object"); 32 33 protocol.clear(); 34 protocol.destroy(); 35 } 36 37 function test_destroy(t) { 38 var protocol = new OpenLayers.Protocol.SQL.Gears(); 39 if (!protocol.supported()) { 40 t.plan(0); 41 return; 42 } 43 44 t.plan(3); 45 46 protocol.destroy(); 47 48 t.eq(protocol.db, null, 49 "destroy nullifies db"); 50 t.eq(protocol.jsonParser, null, 51 "destroy nullifies jsonParser"); 52 t.eq(protocol.wktParser, null, 53 "destroy nullifies wktParser"); 54 } 55 56 function test_read(t) { 57 var protocolCallback, readCallback; 58 var protocolOptions = {callback: protocolCallback}; 59 var readOptions = {callback: readCallback}; 60 61 var protocol = new OpenLayers.Protocol.SQL.Gears(protocolOptions); 62 if (!protocol.supported()) { 63 t.plan(0); 64 return; 65 } 66 67 function okCallback(resp) { 68 t.eq(resp.CLASS_NAME, "OpenLayers.Protocol.Response", 69 "read calls correct callback with a response object"); 70 } 71 72 function failCallback(resp) { 73 t.fail("read calls incorrect callback"); 74 } 75 76 t.plan(4); 77 78 var resp; 79 80 // 2 tests 81 protocolOptions.callback = okCallback; 82 readOptions.callback = failCallback; 83 resp = protocol.read(); 84 t.eq(resp.CLASS_NAME, "OpenLayers.Protocol.Response", 85 "read returns a response object"); 86 87 // 2 test 88 protocolOptions.callback = failCallback; 89 readOptions.callback = okCallback; 90 resp = protocol.read(readOptions); 91 t.eq(resp.CLASS_NAME, "OpenLayers.Protocol.Response", 92 "read returns a response object"); 93 94 protocol.clear(); 95 protocol.destroy(); 96 } 97 98 function test_unfreezeFeature(t) { 99 var protocol = new OpenLayers.Protocol.SQL.Gears(); 100 if (!protocol.supported()) { 101 t.plan(0); 102 return; 103 } 104 105 t.plan(10); 106 107 var feature; 108 var wkt, json, fid, state; 109 110 json = "{\"fake\":\"properties\"}"; 111 fid = "1000"; 112 state = OpenLayers.State.INSERT; 113 114 var row = { 115 fieldByName: function(str) { 116 if (str == "geometry") { 117 return wkt; 118 } 119 if (str == "properties") { 120 return json; 121 } 122 if (str == "fid") { 123 return fid; 124 } 125 if (str == "state") { 126 return state; 127 } 128 } 129 }; 130 131 // 5 tests 132 wkt = "POINT(1 2)"; 133 feature = protocol.unfreezeFeature(row); 134 t.eq(feature.CLASS_NAME, "OpenLayers.Feature.Vector", 135 "unfreezeFeature returns an OpenLayers.Feature.Vector"); 136 t.ok(feature.geometry.x == 1 && feature.geometry.y == 2, 137 "unfreezeFeature returns a feature with correct geometry"); 138 t.eq(feature.attributes.fake, "properties", 139 "unfreezeFeature returns a feature with correct attributes"); 140 t.eq(feature.fid, fid, 141 "unfreezeFeature returns a feature with fid"); 142 t.eq(feature.state, state, 143 "unfreezeFeature returns a feature with state"); 144 145 // 5 tests 146 wkt = protocol.NULL_GEOMETRY; 147 state = protocol.NULL_FEATURE_STATE; 148 feature = protocol.unfreezeFeature(row); 149 t.eq(feature.CLASS_NAME, "OpenLayers.Feature.Vector", 150 "unfreezeFeature returns an OpenLayers.Feature.Vector"); 151 t.eq(feature.geometry, null, 152 "unfreezeFeature returns a feature with correct geometry"); 153 t.eq(feature.attributes.fake, "properties", 154 "unfreezeFeature returns a feature with correct attributes"); 155 t.eq(feature.fid, fid, 156 "unfreezeFeature returns a feature with fid"); 157 t.eq(feature.state, null, 158 "unfreezeFeature returns a feature with state"); 159 160 protocol.clear(); 161 protocol.destroy(); 162 } 163 164 function test_extractFidFromField(t) { 165 var protocol = new OpenLayers.Protocol.SQL.Gears(); 166 if (!protocol.supported()) { 167 t.plan(0); 168 return; 169 } 170 171 t.plan(4); 172 173 var field, fid; 174 175 // fid is a string, field is not prefixed with FID_PREFIX 176 // 1 test 177 field = "10"; 178 res = protocol.extractFidFromField(field); 179 t.eq(res, "10", 180 "extractFidFromField returns expected string"); 181 182 // fid is a string, field is prefixed with FID_PREFIX 183 // 1 test 184 field = protocol.FIX_PREFIX + "10"; 185 res = protocol.extractFidFromField(field); 186 t.eq(res, protocol.FIX_PREFIX + "10", 187 "extractFidFromField returns expected prefixed string"); 188 189 // fid is a number, field is not prefixed with FIX_PREFIX 190 // 1 test 191 protocol.typeOfFid = "number"; 192 field = "10"; 193 res = protocol.extractFidFromField(field); 194 t.eq(res, 10, 195 "extractFidFromField returns expected number"); 196 197 // fid is a number, field is prefixed with FIX_PREFIX 198 // 1 test 199 protocol.typeOfFid = "number"; 200 field = protocol.FID_PREFIX + "10"; 201 res = protocol.extractFidFromField(field); 202 t.eq(res, protocol.FID_PREFIX + "10", 203 "extractFidFromField returns expected prefixed string"); 204 } 205 206 function test_freezeFeature(t) { 207 var protocol = new OpenLayers.Protocol.SQL.Gears(); 208 if (!protocol.supported()) { 209 t.plan(0); 210 return; 211 } 212 213 t.plan(8); 214 215 var feature, res; 216 217 // 4 tests 218 feature = new OpenLayers.Feature.Vector(); 219 feature.geometry = new OpenLayers.Geometry.Point(1, 2); 220 feature.attributes.fake = "properties"; 221 feature.fid = "1000"; 222 feature.state = OpenLayers.State.INSERT; 223 res = protocol.freezeFeature(feature); 224 t.eq(res[0], feature.fid, 225 "freezeFeature returns correct fid"); 226 t.eq(res[1], "POINT(1 2)", 227 "freezeFeature returns correct WKT"); 228 t.eq(res[2], "{\"fake\":\"properties\"}", 229 "freezeFeature returns correct JSON"); 230 t.eq(res[3], feature.state, 231 "freezeFeature returns correct feature state"); 232 233 // 4 tests 234 protocol.saveFeatureState = false; 235 feature = new OpenLayers.Feature.Vector(); 236 feature.attributes.fake = "properties"; 237 feature.fid = "1000"; 238 feature.state = OpenLayers.State.INSERT; 239 res = protocol.freezeFeature(feature); 240 t.eq(res[0], feature.fid, 241 "freezeFeature returns correct fid"); 242 t.eq(res[1], protocol.NULL_GEOMETRY, 243 "freezeFeature returns expected null geom string"); 244 t.eq(res[2], "{\"fake\":\"properties\"}", 245 "freezeFeature returns correct JSON"); 246 t.eq(res[3], protocol.NULL_FEATURE_STATE, 247 "freezeFeature returns expected null feature state string"); 248 249 protocol.clear(); 250 protocol.destroy(); 251 } 252 253 function test_create(t) { 254 var protocol = new OpenLayers.Protocol.SQL.Gears(); 255 if (!protocol.supported()) { 256 t.plan(0); 257 return; 258 } 259 260 t.plan(8); 261 262 var resp; 263 var scope = {"fake": "scope"}; 264 265 var options = { 266 callback: function(resp) { 267 t.eq(resp.CLASS_NAME, "OpenLayers.Protocol.Response", 268 "user callback is passed a response"); 269 t.eq(resp.requestType, "create", 270 "user callback is passed correct request type in resp"); 271 t.ok(this == scope, 272 "user callback called with correct scope"); 273 }, 274 scope: scope 275 }; 276 277 // 4 tests 278 var feature = new OpenLayers.Feature.Vector(); 279 feature.fid = "1000"; 280 feature.attributes.fake = "properties"; 281 feature.state = OpenLayers.State.INSERT; 282 resp = protocol.create([feature], options); 283 t.eq(resp.CLASS_NAME, "OpenLayers.Protocol.Response", 284 "create returns a response"); 285 286 // check what we have in the DB 287 // 4 tests 288 resp = protocol.read({"noFeatureStateReset": true}); 289 t.eq(resp.features.length, 1, 290 "create inserts feature in the DB"); 291 t.eq(resp.features[0].fid, feature.fid, 292 "create inserts feature with correct fid"); 293 t.eq(resp.features[0].attributes.fake, feature.attributes.fake, 294 "create inserts feature with correct attributes"); 295 t.eq(resp.features[0].state, feature.state, 296 "create inserts feature with correct state"); 297 298 protocol.clear(); 299 protocol.destroy(); 300 } 301 302 function test_createOrUpdate(t) { 303 var protocol = new OpenLayers.Protocol.SQL.Gears(); 304 if (!protocol.supported()) { 305 t.plan(0); 306 return; 307 } 308 309 t.plan(5); 310 311 // 1 test 312 var feature = new OpenLayers.Feature.Vector(); 313 feature.fid = "1000"; 314 feature.attributes.fake = "properties"; 315 feature.state = OpenLayers.State.INSERT; 316 resp = protocol.createOrUpdate([feature]); 317 t.eq(resp.CLASS_NAME, "OpenLayers.Protocol.Response", 318 "createOrUpdate returns a response"); 319 320 // check what we have in the DB 321 // 4 tests 322 resp = protocol.read({"noFeatureStateReset": true}); 323 t.eq(resp.features.length, 1, 324 "createOrUpdate inserts feature in the DB"); 325 t.eq(resp.features[0].fid, feature.fid, 326 "createOrUpdate inserts feature with correct fid"); 327 t.eq(resp.features[0].attributes.fake, feature.attributes.fake, 328 "createOrUpdate inserts feature with correct attributes"); 329 t.eq(resp.features[0].state, feature.state, 330 "createOrUpdate inserts feature with correct state"); 331 332 protocol.clear(); 333 protocol.destroy(); 334 } 335 336 function test_delete(t) { 337 var protocol = new OpenLayers.Protocol.SQL.Gears(); 338 if (!protocol.supported()) { 339 t.plan(0); 340 return; 341 } 342 343 t.plan(4); 344 345 function createOneAndDeleteOne(fid, deleteOptions) { 346 var feature = new OpenLayers.Feature.Vector(); 347 feature.fid = fid; 348 feature.attributes.fake = "properties"; 349 feature.state = OpenLayers.State.INSERT; 350 var r = protocol.create([feature]); 351 protocol["delete"](r.reqFeatures, deleteOptions); 352 } 353 354 var resp, fid; 355 356 // 1 test 357 fid = 1000; 358 protocol.saveFeatureState = false; 359 createOneAndDeleteOne(fid) 360 resp = protocol.read(); 361 t.eq(resp.features.length, 0, 362 "delete deletes feature if saveFeatureState is false"); 363 protocol.clear(); 364 365 // 1 test 366 fid = 1000; 367 protocol.saveFeatureState = true; 368 createOneAndDeleteOne(fid); 369 resp = protocol.read(); 370 t.eq(resp.features.length, 1, 371 "delete does not delete feature if saveFeatureState is true"); 372 protocol.clear(); 373 374 // 1 test 375 fid = "1000"; 376 protocol.saveFeatureState = true; 377 createOneAndDeleteOne(fid); 378 resp = protocol.read(); 379 t.eq(resp.features.length, 1, 380 "delete does not delete feature if saveFeatureState is true"); 381 protocol.clear(); 382 383 // 1 test 384 fid = protocol.FID_PREFIX + "1000"; 385 protocol.saveFeatureState = true; 386 createOneAndDeleteOne(fid, {dontDelete: true}); 387 resp = protocol.read(); 388 t.eq(resp.features.length, 0, 389 "delete deletes feature if saveFeatureState is true and fid is prefixed"); 390 protocol.clear(); 391 392 protocol.destroy(); 393 } 394 395 function test_callUserCallback(t) { 396 var protocol = new OpenLayers.Protocol.SQL.Gears(); 397 if (!protocol.supported()) { 398 t.plan(0); 399 return; 400 } 401 402 t.plan(6); 403 404 var options, resp; 405 var scope = {'fake': 'scope'}; 406 407 // test commit callback 408 // 1 tests 409 options = { 410 'callback': function() { 411 t.ok(this == scope, 'callback called with correct scope'); 412 }, 413 'scope': scope 414 }; 415 resp = {'requestType': 'create', 'last': true}; 416 protocol.callUserCallback(options, resp); 417 // 0 test 418 resp = {'requestType': 'create', 'last': false}; 419 protocol.callUserCallback(options, resp); 420 421 // test create callback 422 // 2 tests 423 options = { 424 'create': { 425 'callback': function(r) { 426 t.ok(this == scope, 'callback called with correct scope'); 427 t.ok(r == resp, 'callback called with correct response'); 428 }, 429 'scope': scope 430 } 431 }; 432 resp = {'requestType': 'create'}; 433 protocol.callUserCallback(options, resp); 434 435 // test with both callbacks set 436 // 3 tests 437 options = { 438 'create': { 439 'callback': function(r) { 440 t.ok(this == scope, 'callback called with correct scope'); 441 t.ok(r == resp, 'callback called with correct response'); 442 }, 443 'scope': scope 444 }, 445 'callback': function() { 446 t.ok(this == scope, 'callback called with correct scope'); 447 }, 448 'scope': scope 449 }; 450 resp = {'requestType': 'create', 'last': true}; 451 protocol.callUserCallback(options, resp); 452 453 // no callback set 454 // 0 test 455 options = { 456 'delete': { 457 'callback': function(resp) { 458 t.fail('callback should not get called'); 459 } 460 } 461 }; 462 resp = {'requestType': 'create'}; 463 protocol.callUserCallback(options, resp); 464 465 // cleanup 466 protocol.destroy(); 467 } 468 469 </script> 470 </head> 471 <body> 472 </body> 473 </html> -
tests/Protocol/SQL.html
old new 1 <html> 2 <head> 3 <script src="../../lib/OpenLayers.js"></script> 4 <script type="text/javascript"> 5 6 function test_initialize(t) { 7 t.plan(3); 8 var options = {tableName: 'my_features', 9 databaseName: 'my_database_name'} 10 var protocol = new OpenLayers.Protocol.SQL(options); 11 12 t.ok(protocol instanceof OpenLayers.Protocol.SQL, 13 "new OpenLayers.Protocol.SQL returns object"); 14 15 t.eq(protocol.tableName, options.tableName, "tableName property is set"); 16 t.eq(protocol.databaseName, options.databaseName, "databaseName property is set"); 17 } 18 19 </script> 20 </head> 21 <body> 22 </body> 23 </html> -
tests/list-tests.html
old new 114 114 <li>Projection.html</li> 115 115 <li>Protocol.html</li> 116 116 <li>Protocol/HTTP.html</li> 117 <li>Protocol/SQL.html</li> 118 <li>Protocol/SQL/Gears.html</li> 117 119 <li>Renderer.html</li> 118 120 <li>Renderer/Canvas.html</li> 119 121 <li>Renderer/Elements.html</li> -
lib/OpenLayers/Lang/en.js
old new 116 116 'pagePositionFailed': 117 117 "OpenLayers.Util.pagePosition failed: element with id ${elemId} may be misplaced.", 118 118 119 'end': '' 119 'end': '', 120 121 // console message 122 'evaluateNotImplemented': "evaluate is not implemented for this filter type" 120 123 }; -
lib/OpenLayers/Protocol/SQL/Gears.js
old new 1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD 2 * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the 3 * full text of the license. */ 4 5 /** 6 * @requires Gears/gears_init.js 7 * @requires OpenLayers/Protocol/SQL.js 8 * @requires OpenLayers/Format/JSON.js 9 * @requires OpenLayers/Format/WKT.js 10 */ 11 12 /** 13 * Class: OpenLayers.Protocol.SQL.Gears 14 * This Protocol stores feature in the browser via the Gears Database module 15 * <http://code.google.com/apis/gears/api_database.html>. 16 * 17 * The main advantage is that all the read, create, update and delete operations 18 * can be done offline. 19 * 20 * Inherits from: 21 * - <OpenLayers.Protocol.SQL> 22 */ 23 OpenLayers.Protocol.SQL.Gears = OpenLayers.Class(OpenLayers.Protocol.SQL, { 24 25 /** 26 * Property: FID_PREFIX 27 * {String} 28 */ 29 FID_PREFIX: '__gears_fid__', 30 31 /** 32 * Property: NULL_GEOMETRY 33 * {String} 34 */ 35 NULL_GEOMETRY: '__gears_null_geometry__', 36 37 /** 38 * Property: NULL_FEATURE_STATE 39 * {String} 40 */ 41 NULL_FEATURE_STATE: '__gears_null_feature_state__', 42 43 /** 44 * Property: jsonParser 45 * {<OpenLayers.Format.JSON>} 46 */ 47 jsonParser: null, 48 49 /** 50 * Property: wktParser 51 * {<OpenLayers.Format.WKT>} 52 */ 53 wktParser: null, 54 55 /** 56 * Property: fidRegExp 57 * {RegExp} Regular expression to know whether a feature was 58 * created in offline mode. 59 */ 60 fidRegExp: null, 61 62 /** 63 * Property: saveFeatureState 64 * {Boolean} Whether to save the feature state (<OpenLayers.State>) 65 * into the database, defaults to true. 66 */ 67 saveFeatureState: true, 68 69 /** 70 * Property: typeOfFid 71 * {String} The type of the feature identifier, either "number" or 72 * "string", defaults to "string". 73 */ 74 typeOfFid: "string", 75 76 /** 77 * Property: db 78 * {GearsDatabase} 79 */ 80 db: null, 81 82 /** 83 * Constructor: OpenLayers.Protocol.SQL.Gears 84 */ 85 initialize: function(options) { 86 if (!this.supported()) { 87 return; 88 } 89 OpenLayers.Protocol.SQL.prototype.initialize.apply(this, [options]); 90 this.jsonParser = new OpenLayers.Format.JSON(); 91 this.wktParser = new OpenLayers.Format.WKT(); 92 93 this.fidRegExp = new RegExp('^' + this.FID_PREFIX); 94 this.initializeDatabase(); 95 96 97 }, 98 99 /** 100 * Method: initializeDatabase 101 */ 102 initializeDatabase: function() { 103 this.db = google.gears.factory.create('beta.database'); 104 this.db.open(this.databaseName); 105 this.db.execute( 106 "CREATE TABLE IF NOT EXISTS " + this.tableName + 107 " (fid TEXT UNIQUE, geometry TEXT, properties TEXT," + 108 " state TEXT)"); 109 }, 110 111 /** 112 * APIMethod: destroy 113 * Clean up the protocol. 114 */ 115 destroy: function() { 116 this.db.close(); 117 this.db = null; 118 119 this.jsonParser = null; 120 this.wktParser = null; 121 122 OpenLayers.Protocol.SQL.prototype.destroy.apply(this); 123 }, 124 125 /** 126 * APIMethod: supported 127 * Determine whether a browser supports Gears 128 * 129 * Returns: 130 * {Boolean} The browser supports Gears 131 */ 132 supported: function() { 133 return !!(window.google && google.gears); 134 }, 135 136 /** 137 * Method: read 138 * Read all features from the database and return a 139 * <OpenLayers.Protocol.Response> instance. If the options parameter 140 * contains a callback attribute, the function is called with the response 141 * as a parameter. 142 * 143 * Parameters: 144 * options - {Object} Optional object for configuring the request; it 145 * can have the {Boolean} property "noFeatureStateReset" which 146 * specifies if the state of features read from the Gears 147 * database must be reset to null, if "noFeatureStateReset" 148 * is undefined or false then each feature's state is reset 149 * to null, if "noFeatureStateReset" is true the feature state 150 * is preserved. 151 * 152 * Returns: 153 * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response> 154 * object. 155 */ 156 read: function(options) { 157 options = OpenLayers.Util.applyDefaults(options, this.options); 158 159 var feature, features = []; 160 var rs = this.db.execute("SELECT * FROM " + this.tableName); 161 while (rs.isValidRow()) { 162 feature = this.unfreezeFeature(rs); 163 if (this.evaluateFilter(feature, options.filter)) { 164 if (!options.noFeatureStateReset) { 165 feature.state = null; 166 } 167 features.push(feature); 168 } 169 rs.next(); 170 } 171 rs.close(); 172 173 var resp = new OpenLayers.Protocol.Response({ 174 code: OpenLayers.Protocol.Response.SUCCESS, 175 requestType: "read", 176 features: features 177 }); 178 179 if (options && options.callback) { 180 options.callback.call(options.scope, resp); 181 } 182 183 return resp; 184 }, 185 186 /** 187 * Method: unfreezeFeature 188 * 189 * Parameters: 190 * row - {ResultSet} 191 * 192 * Returns: 193 * {<OpenLayers.Feature.Vector>} 194 */ 195 unfreezeFeature: function(row) { 196 var feature; 197 var wkt = row.fieldByName('geometry'); 198 if (wkt == this.NULL_GEOMETRY) { 199 feature = new OpenLayers.Feature.Vector(); 200 } else { 201 feature = this.wktParser.read(wkt); 202 } 203 204 feature.attributes = this.jsonParser.read( 205 row.fieldByName('properties')); 206 207 feature.fid = this.extractFidFromField(row.fieldByName('fid')); 208 209 var state = row.fieldByName('state'); 210 if (state == this.NULL_FEATURE_STATE) { 211 state = null; 212 } 213 feature.state = state; 214 215 return feature; 216 }, 217 218 /** 219 * Method: extractFidFromField 220 * 221 * Parameters: 222 * field - {String} 223 * 224 * Returns 225 * {String} or {Number} The fid. 226 */ 227 extractFidFromField: function(field) { 228 if (!field.match(this.fidRegExp) && this.typeOfFid == "number") { 229 field = parseFloat(field); 230 } 231 return field; 232 }, 233 234 /** 235 * Method: create 236 * Create new features into the database. 237 * 238 * Parameters: 239 * features - {Array({<OpenLayers.Feature.Vector>})} or 240 * {<OpenLayers.Feature.Vector>} The features to create in 241 * the database. 242 * options - {Object} Optional object for configuring the request. 243 * 244 * Returns: 245 * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response> 246 * object. 247 */ 248 create: function(features, options) { 249 options = OpenLayers.Util.applyDefaults(options, this.options); 250 251 var resp = this.createOrUpdate(features); 252 resp.requestType = "create"; 253 254 if (options && options.callback) { 255 options.callback.call(options.scope, resp); 256 } 257 258 return resp; 259 }, 260 261 /** 262 * Method: update 263 * Construct a request updating modified feature. 264 * 265 * Parameters: 266 * features - {Array({<OpenLayers.Feature.Vector>})} or 267 * {<OpenLayers.Feature.Vector>} The features to update in 268 * the database. 269 * options - {Object} Optional object for configuring the request. 270 * 271 * Returns: 272 * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response> 273 * object. 274 */ 275 update: function(features, options) { 276 options = OpenLayers.Util.applyDefaults(options, this.options); 277 278 var resp = this.createOrUpdate(features); 279 resp.requestType = "update"; 280 281 if (options && options.callback) { 282 options.callback.call(options.scope, resp); 283 } 284 285 return resp; 286 }, 287 288 /** 289 * Method: createOrUpdate 290 * Construct a request for updating or creating features in the 291 * database. 292 * 293 * Parameters: 294 * features - {Array({<OpenLayers.Feature.Vector>})} or 295 * {<OpenLayers.Feature.Vector>} The feature to create or update 296 * in the database. 297 * 298 * Returns: 299 * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response> 300 * object. 301 */ 302 createOrUpdate: function(features) { 303 if (!(features instanceof Array)) { 304 features = [features]; 305 } 306 307 var i, len = features.length, feature; 308 var insertedFeatures = new Array(len); 309 310 for (i = 0; i < len; i++) { 311 feature = features[i]; 312 var params = this.freezeFeature(feature); 313 this.db.execute( 314 "REPLACE INTO " + this.tableName + 315 " (fid, geometry, properties, state)" + 316 " VALUES (?, ?, ?, ?)", 317 params); 318 319 var clone = feature.clone(); 320 clone.fid = this.extractFidFromField(params[0]); 321 insertedFeatures[i] = clone; 322 } 323 324 return new OpenLayers.Protocol.Response({ 325 code: OpenLayers.Protocol.Response.SUCCESS, 326 features: insertedFeatures, 327 reqFeatures: features 328 }); 329 }, 330 331 /** 332 * Method: freezeFeature 333 * 334 * Parameters: 335 * feature - {<OpenLayers.Feature.Vector>} 336 * state - {String} The feature state to store in the database. 337 * 338 * Returns: 339 * {Array} 340 */ 341 freezeFeature: function(feature) { 342 // 2 notes: 343 // - fid might not be a string 344 // - getFeatureStateForFreeze needs the feature fid to it's stored 345 // in the feature here 346 feature.fid = feature.fid != null ? 347 "" + feature.fid : OpenLayers.Util.createUniqueID(this.FID_PREFIX); 348 349 var geometry = feature.geometry != null ? 350 feature.geometry.toString() : this.NULL_GEOMETRY; 351 352 var properties = this.jsonParser.write(feature.attributes); 353 354 var state = this.getFeatureStateForFreeze(feature); 355 356 return [feature.fid, geometry, properties, state]; 357 }, 358 359 /** 360 * Method: getFeatureStateForFreeze 361 * Get the state of the feature to store into the database. 362 * 363 * Parameters: 364 * feature - {<OpenLayers.Feature.Vector>} The feature. 365 * 366 * Returns 367 * {String} The state 368 */ 369 getFeatureStateForFreeze: function(feature) { 370 var state; 371 if (!this.saveFeatureState) { 372 state = this.NULL_FEATURE_STATE; 373 } else if (this.createdOffline(feature)) { 374 // if the feature was created in offline mode, its 375 // state must remain INSERT 376 state = OpenLayers.State.INSERT; 377 } else { 378 state = feature.state; 379 } 380 return state; 381 }, 382 383 /** 384 * Method: delete 385 * Delete features from the database. 386 * 387 * Parameters: 388 * features - {Array({<OpenLayers.Feature.Vector>})} or 389 * {<OpenLayers.Feature.Vector>} 390 * options - {Object} Optional object for configuring the request. 391 * This object is modified and should not be reused. 392 * 393 * Returns: 394 * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response> 395 * object. 396 */ 397 "delete": function(features, options) { 398 if (!(features instanceof Array)) { 399 features = [features]; 400 } 401 402 options = OpenLayers.Util.applyDefaults(options, this.options); 403 404 var i, len, feature; 405 for (i = 0, len = features.length; i < len; i++) { 406 feature = features[i]; 407 408 // if saveFeatureState is set to true and if the feature wasn't created 409 // in offline mode we don't delete it in the database but just update 410 // it state column 411 if (this.saveFeatureState && !this.createdOffline(feature)) { 412 var toDelete = feature.clone(); 413 toDelete.fid = feature.fid; 414 if (toDelete.geometry) { 415 toDelete.geometry.destroy(); 416 toDelete.geometry = null; 417 } 418 toDelete.state = feature.state; 419 this.createOrUpdate(toDelete); 420 } else { 421 this.db.execute( 422 "DELETE FROM " + this.tableName + 423 " WHERE fid = ?", [feature.fid]); 424 } 425 } 426 427 var resp = new OpenLayers.Protocol.Response({ 428 code: OpenLayers.Protocol.Response.SUCCESS, 429 requestType: "delete", 430 reqFeatures: features 431 }); 432 433 if (options && options.callback) { 434 options.callback.call(options.scope, resp); 435 } 436 437 return resp; 438 }, 439 440 /** 441 * Method: createdOffline 442 * Returns true if the feature had a feature id when it was created in 443 * the Gears database, false otherwise; this is determined by 444 * checking the form of the feature's fid value. 445 * 446 * Parameters: 447 * feature - {<OpenLayers.Feature.Vector>} 448 * 449 * Returns: 450 * {Boolean} 451 */ 452 createdOffline: function(feature) { 453 return (typeof feature.fid == "string" && 454 !!(feature.fid.match(this.fidRegExp))); 455 }, 456 457 /** 458 * Method: commit 459 * Go over the features and for each take action 460 * based on the feature state. Possible actions are create, 461 * update and delete. 462 * 463 * Parameters: 464 * features - {Array({<OpenLayers.Feature.Vector>})} 465 * options - {Object} Object whose possible keys are "create", "update", 466 * "delete", "callback" and "scope", the values referenced by the 467 * first three are objects as passed to the "create", "update", and 468 * "delete" methods, the value referenced by the "callback" key is 469 * a function which is called when the commit operation is complete 470 * using the scope referenced by the "scope" key. 471 * 472 * Returns: 473 * {Array({<OpenLayers.Protocol.Response>})} An array of 474 * <OpenLayers.Protocol.Response> objects, one per request made 475 * to the database. 476 */ 477 commit: function(features, options) { 478 var opt, resp = [], nRequests = 0, nResponses = 0; 479 480 function callback(resp) { 481 if (++nResponses < nRequests) { 482 resp.last = false; 483 } 484 this.callUserCallback(options, resp); 485 } 486 487 var feature, toCreate = [], toUpdate = [], toDelete = []; 488 for (var i = features.length - 1; i >= 0; i--) { 489 feature = features[i]; 490 switch (feature.state) { 491 case OpenLayers.State.INSERT: 492 toCreate.push(feature); 493 break; 494 case OpenLayers.State.UPDATE: 495 toUpdate.push(feature); 496 break; 497 case OpenLayers.State.DELETE: 498 toDelete.push(feature); 499 break; 500 } 501 } 502 if (toCreate.length > 0) { 503 nRequests++; 504 opt = OpenLayers.Util.applyDefaults( 505 {"callback": callback, "scope": this}, 506 options.create 507 ); 508 resp.push(this.create(toCreate, opt)); 509 } 510 if (toUpdate.length > 0) { 511 nRequests++; 512 opt = OpenLayers.Util.applyDefaults( 513 {"callback": callback, "scope": this}, 514 options.update 515 ); 516 resp.push(this.update(toUpdate, opt)); 517 } 518 if (toDelete.length > 0) { 519 nRequests++; 520 opt = OpenLayers.Util.applyDefaults( 521 {"callback": callback, "scope": this}, 522 options["delete"] 523 ); 524 resp.push(this["delete"](toDelete, opt)); 525 } 526 527 return resp; 528 }, 529 530 /** 531 * Method: clear 532 * Removes all rows of the table. 533 */ 534 clear: function() { 535 this.db.execute("DELETE FROM " + this.tableName); 536 }, 537 538 /** 539 * Method: callUserCallback 540 * This method is called from within commit each time a request is made 541 * to the database, it is responsible for calling the user-supplied 542 * callbacks. 543 * 544 * Parameters: 545 * options - {Object} The map of options passed to the commit call. 546 * resp - {<OpenLayers.Protocol.Response>} 547 */ 548 callUserCallback: function(options, resp) { 549 var opt = options[resp.requestType]; 550 if (opt && opt.callback) { 551 opt.callback.call(opt.scope, resp); 552 } 553 if (resp.last && options.callback) { 554 options.callback.call(options.scope); 555 } 556 }, 557 558 CLASS_NAME: "OpenLayers.Protocol.SQL.Gears" 559 }); -
lib/OpenLayers/Protocol/SQL.js
old new 1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD 2 * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the 3 * full text of the license. */ 4 5 /** 6 * @requires OpenLayers/Protocol.js 7 */ 8 9 /** 10 * Class: OpenLayers.Protocol.SQL 11 * Abstract SQL protocol class. Not to be instantiated directly. Use 12 * one of the SQL protocol subclasses instead. 13 * 14 * Inherits from: 15 * - <OpenLayers.Protocol> 16 */ 17 OpenLayers.Protocol.SQL = OpenLayers.Class(OpenLayers.Protocol, { 18 19 /** 20 * APIProperty: databaseName 21 * {String} 22 */ 23 databaseName: 'ol', 24 25 /** 26 * APIProperty: tableName 27 * Name of the database table into which Features should be saved. 28 */ 29 tableName: "ol_vector_features", 30 31 /** 32 * Property: postReadFiltering 33 * {Boolean} Whether the filter (if there's one) must be applied after 34 * the features have been read from the database; for example the 35 * BBOX strategy passes the read method a BBOX spatial filter, if 36 * postReadFiltering is true every feature read from the database 37 * will go through the BBOX spatial filter, which can be costly; 38 * defaults to true. 39 */ 40 postReadFiltering: true, 41 42 /** 43 * Constructor: OpenLayers.Protocol.SQL 44 */ 45 initialize: function(options) { 46 OpenLayers.Protocol.prototype.initialize.apply(this, [options]); 47 }, 48 49 /** 50 * APIMethod: destroy 51 * Clean up the protocol. 52 */ 53 destroy: function() { 54 OpenLayers.Protocol.prototype.destroy.apply(this); 55 }, 56 57 /** 58 * APIMethod: supported 59 * This should be overridden by specific subclasses 60 * 61 * Returns: 62 * {Boolean} Whether or not the browser supports the SQL backend 63 */ 64 supported: function() { 65 return false; 66 }, 67 68 /** 69 * Method: evaluateFilter 70 * If postReadFiltering is true evaluate the filter against the feature 71 * and return the result of the evaluation, otherwise return true. 72 * 73 * Parameters: 74 * {<OpenLayers.Feature.Vector>} The feature. 75 * {<OpenLayers.Filter>} The filter. 76 * 77 * Returns: 78 * {Boolean} true if postReadFiltering if false, the result of the 79 * filter evaluation otherwise. 80 */ 81 evaluateFilter: function(feature, filter) { 82 return filter && this.postReadFiltering ? 83 filter.evaluate(feature) : true; 84 }, 85 86 CLASS_NAME: "OpenLayers.Protocol.SQL" 87 }); -
lib/Gears/gears_init.js
old new 1 /* 2 * Copyright 2007, Google Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * this list of conditions and the following disclaimer in the documentation 11 * and/or other materials provided with the distribution. 12 * 3. Neither the name of Google Inc. nor the names of its contributors may be 13 * used to endorse or promote products derived from this software without 14 * specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * Sets up google.gears.*, which is *the only* supported way to access Gears. 28 * 29 * Circumvent this file at your own risk! 30 * 31 * In the future, Gears may automatically define google.gears.* without this 32 * file. Gears may use these objects to transparently fix bugs and compatibility 33 * issues. Applications that use the code below will continue to work seamlessly 34 * when that happens. 35 */ 36 37 (function() { 38 // We are already defined. Hooray! 39 if (window.google && google.gears) { 40 return; 41 } 42 43 var factory = null; 44 45 // Firefox 46 if (typeof GearsFactory != 'undefined') { 47 factory = new GearsFactory(); 48 } else { 49 // IE 50 try { 51 factory = new ActiveXObject('Gears.Factory'); 52 // privateSetGlobalObject is only required and supported on WinCE. 53 if (factory.getBuildInfo().indexOf('ie_mobile') != -1) { 54 factory.privateSetGlobalObject(this); 55 } 56 } catch (e) { 57 // Safari 58 if ((typeof navigator.mimeTypes != 'undefined') 59 && navigator.mimeTypes["application/x-googlegears"]) { 60 factory = document.createElement("object"); 61 factory.style.display = "none"; 62 factory.width = 0; 63 factory.height = 0; 64 factory.type = "application/x-googlegears"; 65 document.documentElement.appendChild(factory); 66 } 67 } 68 } 69 70 // *Do not* define any objects if Gears is not installed. This mimics the 71 // behavior of Gears defining the objects in the future. 72 if (!factory) { 73 return; 74 } 75 76 // Now set up the objects, being careful not to overwrite anything. 77 // 78 // Note: In Internet Explorer for Windows Mobile, you can't add properties to 79 // the window object. However, global objects are automatically added as 80 // properties of the window object in all browsers. 81 if (!window.google) { 82 google = {}; 83 } 84 85 if (!google.gears) { 86 google.gears = {factory: factory}; 87 } 88 })(); -
lib/OpenLayers.js
old new 83 83 "OpenLayers/Tween.js", 84 84 "Rico/Corner.js", 85 85 "Rico/Color.js", 86 "Gears/gears_init.js", 86 87 "OpenLayers/Ajax.js", 87 88 "OpenLayers/Request.js", 88 89 "OpenLayers/Request/XMLHttpRequest.js", … … 185 186 "OpenLayers/Strategy/Fixed.js", 186 187 "OpenLayers/Protocol.js", 187 188 "OpenLayers/Protocol/HTTP.js", 189 "OpenLayers/Protocol/SQL.js", 190 "OpenLayers/Protocol/SQL/Gears.js", 188 191 "OpenLayers/Layer/PointTrack.js", 189 192 "OpenLayers/Layer/GML.js", 190 193 "OpenLayers/Style.js", -
examples/protocol-gears.html
old new 1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <link rel="stylesheet" href="../theme/default/style.css" type="text/css" /> 4 <link rel="stylesheet" href="style.css" type="text/css" /> 5 <style type="text/css"> 6 .float-left { 7 float: left; 8 } 9 .clear-left { 10 clear: left; 11 } 12 </style> 13 <script src="../lib/OpenLayers.js"></script> 14 <script type="text/javascript"> 15 var map, vector, protocol, modify; 16 17 function init() { 18 // create Gears protocol 19 protocol = new OpenLayers.Protocol.SQL.Gears({ 20 databaseName: "db_name", 21 tableName: "table_name", 22 saveFeatureState: false 23 }); 24 25 if (!GearsIsSupported()) { 26 return; 27 } 28 29 map = new OpenLayers.Map("map"); 30 31 // create base layer 32 var layer = new OpenLayers.Layer.WMS("OpenLayers WMS", 33 "http://labs.metacarta.com/wms/vmap0", 34 {"layers": "basic"} 35 ); 36 map.addLayer(layer); 37 38 // create vector layer 39 vector = new OpenLayers.Layer.Vector("Vector", { 40 protocol: protocol, 41 strategies : [new OpenLayers.Strategy.Fixed()], 42 eventListeners: { 43 featuremodified: function(obj) { 44 if (obj.feature.state != OpenLayers.State.INSERT && 45 obj.feature.state != OpenLayers.State.DELETE) { 46 47 obj.feature.state = OpenLayers.State.UPDATE; 48 } 49 displayStatus(); 50 } 51 } 52 }); 53 map.addLayer(vector); 54 55 // create modify feature control 56 modify = new OpenLayers.Control.ModifyFeature(vector); 57 58 // create editing panel 59 var panel = new OpenLayers.Control.Panel({ 60 displayClass: "olControlEditingToolbar" 61 }); 62 63 var navigation = new OpenLayers.Control.Navigation({ 64 eventListeners: { 65 activate: function(obj) { 66 modify.activate(); 67 }, 68 deactivate: function(obj) { 69 modify.deactivate(); 70 } 71 } 72 }); 73 74 var editing = new OpenLayers.Control.DrawFeature( 75 vector, OpenLayers.Handler.Polygon, { 76 displayClass: "olControlDrawFeaturePolygon", 77 eventListeners: { 78 featureadded: function(obj) { 79 obj.feature.state = OpenLayers.State.INSERT; 80 displayStatus(); 81 } 82 } 83 }); 84 panel.addControls([navigation, editing]); 85 panel.defaultControl = navigation; 86 87 // add controls to the map 88 map.addControl(modify); 89 map.addControl(panel); 90 91 // center the map 92 map.setCenter(new OpenLayers.LonLat(5, 40), 5); 93 } 94 95 function displayResult(txt) { 96 if (window.resultDomElement === undefined) { 97 window.resultDomElement = OpenLayers.Util.getElement("last-result"); 98 } 99 resultDomElement.innerHTML = txt; 100 displayStatus(); 101 } 102 103 function displayStatus() { 104 if (window.statusDomElement === undefined) { 105 window.statusDomElement = OpenLayers.Util.getElement("status"); 106 } 107 108 var createCnt = 0; 109 var updateCnt = 0; 110 var deleteCnt = 0; 111 var i, len, state; 112 for (i = 0, len = vector.features.length; i < len; i++) { 113 state = vector.features[i].state; 114 if (state == OpenLayers.State.INSERT) { 115 createCnt++; 116 } else if (state == OpenLayers.State.UPDATE) { 117 updateCnt++; 118 } else if (state == OpenLayers.State.DELETE) { 119 deleteCnt++; 120 } 121 } 122 statusDomElement.innerHTML = createCnt + " features to create, " + 123 updateCnt + " features to update, " + 124 deleteCnt + " features to delete"; 125 } 126 127 function GearsIsSupported() { 128 if (!protocol.supported()) { 129 OpenLayers.Console.userError("You must install Gears prior to using this example"); 130 return false; 131 } 132 return true; 133 } 134 135 function featuresWithState(state) { 136 var list = []; 137 var i, len, feature; 138 for (i = 0, len = vector.features.length; i < len; i++) { 139 feature = vector.features[i]; 140 if (feature.state == state) { 141 list.push(feature); 142 } 143 } 144 return list; 145 } 146 147 function _sync() { 148 if (!GearsIsSupported()) { 149 return; 150 } 151 var resp = protocol.read(); 152 if (!resp.success()) { 153 OpenLayers.Console.error("reading from Gears DB failed"); 154 return; 155 } 156 vector.destroyFeatures(); 157 if (!resp.features || resp.features.length <= 0) { 158 displayResult("No features to read"); 159 return; 160 } 161 vector.addFeatures(resp.features); 162 displayResult("features successfully read"); 163 } 164 165 function _commit() { 166 if (!GearsIsSupported()) { 167 return; 168 } 169 var error = false; 170 function callback(resp) { 171 if (error) { 172 return; 173 } 174 if (!resp.success()) { 175 OpenLayers.Console.error("Commiting to Gears DB failed"); 176 error = true; 177 return; 178 } 179 modify.selectControl.unselectAll() 180 181 if (resp.reqFeatures) { 182 vector.destroyFeatures(resp.reqFeatures); 183 } 184 if (resp.features) { 185 vector.addFeatures(resp.features); 186 } 187 } 188 if (vector.features.length > 0) { 189 protocol.commit(vector.features, { 190 "create": { 191 callback: callback 192 }, 193 "update": { 194 callback: callback 195 }, 196 "delete": { 197 callback: callback 198 } 199 }); 200 if (!error) { 201 displayResult("features successfully committed"); 202 } 203 } else { 204 displayResult("no features to commit"); 205 } 206 } 207 208 function _delete() { 209 if (!GearsIsSupported()) { 210 return; 211 } 212 var feature = vector.selectedFeatures[0]; 213 if (feature) { 214 modify.selectControl.unselectAll() 215 feature.state = OpenLayers.State.DELETE; 216 displayStatus(); 217 } 218 } 219 </script> 220 </head> 221 <body onload="init()"> 222 <h1 id="title">Gears Protocol Example</h1> 223 224 <div id="tags"> 225 </div> 226 <p id="shortdesc"> 227 Shows the usage of the Gears protocol. 228 </p> 229 230 <div class="float-left"> 231 <div id="map" class="smallmap"></div> 232 </div> 233 234 <div> 235 <a href="javascript:_sync()">Sync</a> 236 <p>The Sync link destroys the features currently in the layer, reads 237 features from the Gears database, and adds them to the layer. 238 Uncommitted features will be lost.</p> 239 240 <a href="javascript:_commit()">Commit</a> 241 <p>The Commit link commits to the Gears database the features that are 242 marked as INSERT, UPDATE or DELETE.</p> 243 244 <a href="javascript:_delete()">Delete</a> 245 <p>The Delete link marks the selected feature as DELETE. To select a feature 246 click choose the navigation control in the editing toolbar.</p> 247 </div> 248 249 <div style="margin-top: 30px"> 250 <p>Status: <span id="status"></span></p> 251 <p>Result: <span id="last-result"></span></p> 252 </div> 253 254 <div class="clear-left" id="docs"> 255 <p>This example demonstrates the usage of OpenLayers Gears protocol to 256 read/create/update/delete features from/to the Gears database. 257 <a href="http://gears.google.com/">Gears</a> must obviously be installed 258 in your browser for this example to work.</p> 259 </div> 260 </body> 261 </html>
