[OpenLayers-Commits] r11326 - in sandbox/jgrocha/openlayers: examples lib/OpenLayers/Protocol/SQL

commits-20090109 at openlayers.org commits-20090109 at openlayers.org
Wed Feb 23 09:22:27 EST 2011


Author: jgrocha
Date: 2011-02-23 06:22:27 -0800 (Wed, 23 Feb 2011)
New Revision: 11326

Added:
   sandbox/jgrocha/openlayers/examples/protocol-localsql.html
   sandbox/jgrocha/openlayers/lib/OpenLayers/Protocol/SQL/LocalSQL.js
Log:
very first version of the new protocol LocalSQL for local storage

Added: sandbox/jgrocha/openlayers/examples/protocol-localsql.html
===================================================================
--- sandbox/jgrocha/openlayers/examples/protocol-localsql.html	                        (rev 0)
+++ sandbox/jgrocha/openlayers/examples/protocol-localsql.html	2011-02-23 14:22:27 UTC (rev 11326)
@@ -0,0 +1,268 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+	<head><meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" /><meta name="apple-mobile-web-app-capable" content="yes" />
+		<link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
+		<link rel="stylesheet" href="style.css" type="text/css" />
+		<style type="text/css">
+	.float-left {
+		float: left;
+	}
+	.clear-left {
+		clear: left;
+	}
+		</style>
+		<script src="../lib/OpenLayers.js">
+		</script>
+		<script type="text/javascript">
+	var map, vector, protocol, modify;
+
+	function init() {
+		// create Gears protocol
+		protocol = new OpenLayers.Protocol.SQL.LocalSQL({
+			databaseName: "db_name",
+			tableName: "table_name",
+			saveFeatureState: false
+		});
+
+		if (!LocalSQLIsSupported()) {
+			return;
+		}
+
+		map = new OpenLayers.Map("map");
+
+		// create base layer
+		var layer = new OpenLayers.Layer.WMS("OpenLayers WMS",
+		"http://vmap0.tiles.osgeo.org/wms/vmap0",
+		{"layers": "basic"}
+		);
+		map.addLayer(layer);
+
+		// create vector layer
+		vector = new OpenLayers.Layer.Vector("Vector", {
+			protocol: protocol,
+			strategies : [new OpenLayers.Strategy.Fixed()],
+			eventListeners: {
+				featuremodified: function(obj) {
+					displayStatus();
+				}
+			}
+		});
+		map.addLayer(vector);
+
+		// create modify feature control
+		modify = new OpenLayers.Control.ModifyFeature(vector);
+
+		// create editing panel
+		var panel = new OpenLayers.Control.Panel({
+			displayClass: "olControlEditingToolbar"
+		});
+
+		var navigation = new OpenLayers.Control.Navigation({
+			eventListeners: {
+				activate: function(obj) {
+					modify.activate();
+				},
+				deactivate: function(obj) {
+					modify.deactivate();
+				}
+			}
+		});
+
+		var editing = new OpenLayers.Control.DrawFeature(
+		vector, OpenLayers.Handler.Polygon, {
+			displayClass: "olControlDrawFeaturePolygon",
+			eventListeners: {
+				featureadded: function(obj) {
+					obj.feature.state = OpenLayers.State.INSERT;
+					displayStatus();
+				}
+			}
+		});
+		panel.addControls([navigation, editing]);
+		panel.defaultControl = navigation;
+
+		// add controls to the map
+		map.addControl(modify);
+		map.addControl(panel);
+
+		// center the map
+		map.setCenter(new OpenLayers.LonLat(5, 40), 5);
+	}
+
+	function displayResult(txt) {
+		if (window.resultDomElement === undefined) {
+			window.resultDomElement = OpenLayers.Util.getElement("last-result");
+		}
+		resultDomElement.innerHTML = txt;
+		displayStatus();
+	}
+
+	function displayStatus() {
+		if (window.statusDomElement === undefined) {
+			window.statusDomElement = OpenLayers.Util.getElement("status");
+		}
+
+		var createCnt = 0;
+		var updateCnt = 0;
+		var deleteCnt = 0;
+		var i, len, state;
+		for (i = 0, len = vector.features.length; i < len; i++) {
+			state = vector.features[i].state;
+			if (state == OpenLayers.State.INSERT) {
+				createCnt++;
+			} else if (state == OpenLayers.State.UPDATE) {
+				updateCnt++;
+			} else if (state == OpenLayers.State.DELETE) {
+				deleteCnt++;
+			}
+		}
+		statusDomElement.innerHTML = createCnt + " features to create, " +
+		updateCnt + " features to update, " +
+		deleteCnt + " features to delete";
+	}
+
+	function LocalSQLIsSupported() {
+		if (!protocol.supported()) {
+			OpenLayers.Console.userError("This browser does not support this example");
+			return false;
+		}
+		return true;
+	}
+
+	function featuresWithState(state) {
+		var list = [];
+		var i, len, feature;
+		for (i = 0, len = vector.features.length; i < len; i++) {
+			feature = vector.features[i];
+			if (feature.state == state) {
+				list.push(feature);
+			}
+		}
+		return list;
+	}
+
+	function _sync() {
+		if (!LocalSQLIsSupported()) {
+			return;
+		}
+		var resp = protocol.read();
+		if (!resp.success()) {
+			OpenLayers.Console.error("reading from Gears DB failed");
+			return;
+		}
+		vector.destroyFeatures();
+		if (!resp.features || resp.features.length <= 0) {
+			displayResult("No features to read");
+			return;
+		}
+		vector.addFeatures(resp.features);
+		displayResult("features successfully read");
+	}
+
+	function _commit() {
+		if (!LocalSQLIsSupported()) {
+			return;
+		}
+		var error = false;
+		function callback(resp) {
+			if (error) {
+				return;
+			}
+			if (!resp.success()) {
+				OpenLayers.Console.error("Commiting to Gears DB failed");
+				error = true;
+				return;
+			}
+			modify.selectControl.unselectAll()
+
+			if (resp.reqFeatures) {
+				vector.destroyFeatures(resp.reqFeatures);
+			}
+			if (resp.features) {
+				vector.addFeatures(resp.features);
+			}
+		}
+
+		if (vector.features.length > 0) {
+			protocol.commit(vector.features, {
+				"create": {
+					callback: callback
+				},
+				"update": {
+					callback: callback
+				},
+				"delete": {
+					callback: callback
+				}
+			});
+			if (!error) {
+				displayResult("features successfully committed");
+			}
+		} else {
+			displayResult("no features to commit");
+		}
+	}
+
+	function _delete() {
+		if (!LocalSQLIsSupported()) {
+			return;
+		}
+		var feature = vector.selectedFeatures[0];
+		if (feature) {
+			modify.selectControl.unselectAll()
+			feature.state = OpenLayers.State.DELETE;
+			displayStatus();
+		}
+	}
+		</script>
+	</head>
+	<body onload="init()">
+		<h1 id="title">Local SQL Storage Protocol Example</h1>
+		<div id="tags">
+			Open Layers Protocol, Local SQL Sotarage
+		</div>
+		<p id="shortdesc">
+			Shows the usage of the local SQL storage protocol.
+		</p>
+		<div class="float-left">
+			<div id="map" class="smallmap">
+			</div>
+		</div>
+		<div>
+			<a href="javascript:_sync()">Sync</a>
+			<p>
+				The Sync link destroys the features currently in the layer, reads
+				features from the local SQL storage, and adds them to the layer.
+				Uncommitted features will be lost.
+			</p>
+			<a href="javascript:_commit()">Commit</a>
+			<p>
+				The Commit link commits to the Gears database the features that are
+				marked as INSERT, UPDATE or DELETE.
+			</p>
+			<a href="javascript:_delete()">Delete</a>
+			<p>
+				The Delete link marks the selected feature as DELETE. To select a feature
+				click choose the navigation control in the editing toolbar.
+			</p>
+		</div>
+		<div style="margin-top: 30px">
+			<p>
+				Status:
+				<span id="status"></span>
+			</p>
+			<p>
+				Result:
+				<span id="last-result"></span>
+			</p>
+		</div>
+		<div class="clear-left" id="docs">
+			<p>
+				This example demonstrates the usage of OpenLayers Local SQL Storage protocol to
+				read/create/update/delete features from/to the browser's local database.
+
+				This
+				<a href="http://www.w3.org/TR/webdatabase/">specification</a> defines an API for storing data in databases that can be queried using a variant of SQL.
+			</p>
+		</div>
+	</body>
+</html>

Added: sandbox/jgrocha/openlayers/lib/OpenLayers/Protocol/SQL/LocalSQL.js
===================================================================
--- sandbox/jgrocha/openlayers/lib/OpenLayers/Protocol/SQL/LocalSQL.js	                        (rev 0)
+++ sandbox/jgrocha/openlayers/lib/OpenLayers/Protocol/SQL/LocalSQL.js	2011-02-23 14:22:27 UTC (rev 11326)
@@ -0,0 +1,575 @@
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
+* full list of contributors). Published under the Clear BSD license.
+* See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+* full text of the license. */
+
+/**
+ * @requires Gears/gears_init.js
+ * @requires OpenLayers/Protocol/SQL.js
+ * @requires OpenLayers/Format/JSON.js
+ * @requires OpenLayers/Format/WKT.js
+ */
+
+/**
+ * Class: OpenLayers.Protocol.SQL.Gears
+ * This Protocol stores feature in the browser via the Gears Database module
+ * <http://code.google.com/apis/gears/api_database.html>.
+ *
+ * The main advantage is that all the read, create, update and delete operations
+ * can be done offline.
+ *
+ * Inherits from:
+ *  - <OpenLayers.Protocol.SQL>
+ */
+OpenLayers.Protocol.SQL.LocalSQL = OpenLayers.Class(OpenLayers.Protocol.SQL, {
+
+	/**
+ 	* Property: FID_PREFIX
+ 	* {String}
+ 	*/
+	FID_PREFIX: '__localsql_fid__',
+
+	/**
+ 	* Property: NULL_GEOMETRY
+ 	* {String}
+ 	*/
+	NULL_GEOMETRY: '__localsql_null_geometry__',
+
+	/**
+ 	* Property: NULL_FEATURE_STATE
+ 	* {String}
+ 	*/
+	NULL_FEATURE_STATE: '__localsql_null_feature_state__',
+
+	/**
+ 	* Property: jsonParser
+ 	* {<OpenLayers.Format.JSON>}
+ 	*/
+	jsonParser: null,
+
+	/**
+ 	* Property: wktParser
+ 	* {<OpenLayers.Format.WKT>}
+ 	*/
+	wktParser: null,
+
+	/**
+ 	* Property: fidRegExp
+ 	* {RegExp} Regular expression to know whether a feature was
+ 	*      created in offline mode.
+ 	*/
+	fidRegExp: null,
+
+	/**
+ 	* Property: saveFeatureState
+ 	* {Boolean} Whether to save the feature state (<OpenLayers.State>)
+ 	*      into the database, defaults to true.
+ 	*/
+	saveFeatureState: true,
+
+	/**
+ 	* Property: typeOfFid
+ 	* {String} The type of the feature identifier, either "number" or
+ 	*      "string", defaults to "string".
+ 	*/
+	typeOfFid: "string",
+
+	/**
+ 	* Property: db
+ 	* {Web SQL Database}
+ 	*/
+	db: null,
+
+	/**
+ 	* Constructor: OpenLayers.Protocol.SQL.LocalSQL
+ 	* tested, jgr
+ 	*/
+	initialize: function(options) {
+		if (!this.supported()) {
+			return;
+		}
+		OpenLayers.Protocol.SQL.prototype.initialize.apply(this, [options]);
+		this.jsonParser = new OpenLayers.Format.JSON();
+		this.wktParser = new OpenLayers.Format.WKT();
+		this.fidRegExp = new RegExp('^' + this.FID_PREFIX);
+		this.initializeDatabase();
+
+	},
+	/**
+ 	* Method: initializeDatabase
+ 	* tested, jgr
+ 	*/
+	initializeDatabase: function() {
+		this.db = window.openDatabase('Open Layers', '1.0', this.databaseName, 8*1024);
+		this.db.transaction( function(tx) {
+			tx.executeSql("create table if not exists " + this.tableName +
+			" (fid TEXT UNIQUE, geometry TEXT, properties TEXT, state TEXT)",
+			[], function() {
+				console.log("success create table if not exist");
+			}
+			);
+		});
+	},
+	/**
+ 	* APIMethod: destroy
+ 	* Clean up the protocol.
+ 	* fixme, jgr
+ 	*/
+	destroy: function() {
+		/* I really do not know how to destroy the database. I will check it later */
+		this.db.close();
+		this.db = null;
+		this.jsonParser = null;
+		this.wktParser = null;
+		OpenLayers.Protocol.SQL.prototype.destroy.apply(this);
+	},
+	/**
+ 	* APIMethod: supported
+ 	* Determine whether a browser supports Local SQL Storage
+ 	*
+ 	* Returns:
+ 	* {Boolean} The browser supports Local SQL Storage
+ 	*/
+	supported: function() {
+		return !!(window.openDatabase);
+	},
+	/**
+ 	* APIMethod: read
+ 	* Read all features from the database and return a
+ 	* <OpenLayers.Protocol.Response> instance. If the options parameter
+ 	* contains a callback attribute, the function is called with the response
+ 	* as a parameter.
+ 	*
+ 	* Parameters:
+ 	* options - {Object} Optional object for configuring the request; it
+ 	*      can have the {Boolean} property "noFeatureStateReset" which
+ 	*      specifies if the state of features read from the Gears
+ 	*      database must be reset to null, if "noFeatureStateReset"
+ 	*      is undefined or false then each feature's state is reset
+ 	*      to null, if "noFeatureStateReset" is true the feature state
+ 	*      is preserved.
+ 	*
+ 	* Returns:
+ 	* {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+ 	*      object.
+ 	* fixme, jgr
+ 	* check the possible options that can be passed
+ 	*/
+	read: function(options) {
+		OpenLayers.Protocol.prototype.read.apply(this, arguments);
+		options = OpenLayers.Util.applyDefaults(options, this.options);
+
+		var feature, features = [];
+		var features = [];
+		this.db.transaction( function(tx) {
+			tx.executeSql("select * from " + this.tableName, [], function(tx, results) {
+				for (i = 0; i < results.rows.length; i++) {
+					feature = this.unfreezeFeature(results.rows.item(i));
+					if (this.evaluateFilter(feature, options.filter)) {
+						if (!options.noFeatureStateReset) {
+							feature.state = null;
+						}
+						features.push(feature);
+					}
+				}
+			}, function() {
+			});
+		});
+		var resp = new OpenLayers.Protocol.Response({
+			code: OpenLayers.Protocol.Response.SUCCESS,
+			requestType: "read",
+			features: features
+		});
+
+		if (options && options.callback) {
+			options.callback.call(options.scope, resp);
+		}
+
+		return resp;
+	},
+	/**
+ 	* Method: unfreezeFeature
+ 	*
+ 	* Parameters:
+ 	* row - {ResultSet}
+ 	*
+ 	* Returns:
+ 	* {<OpenLayers.Feature.Vector>}
+ 	*/
+	unfreezeFeature: function(row) {
+		var feature;
+		var wkt = row.fieldByName('geometry');
+		if (wkt == this.NULL_GEOMETRY) {
+			feature = new OpenLayers.Feature.Vector();
+		} else {
+			feature = this.wktParser.read(wkt);
+		}
+
+		feature.attributes = this.jsonParser.read(
+		row.fieldByName('properties'));
+
+		feature.fid = this.extractFidFromField(row.fieldByName('fid'));
+
+		var state = row.fieldByName('state');
+		if (state == this.NULL_FEATURE_STATE) {
+			state = null;
+		}
+		feature.state = state;
+
+		return feature;
+	},
+	/**
+ 	* Method: extractFidFromField
+ 	*
+ 	* Parameters:
+ 	* field - {String}
+ 	*
+ 	* Returns
+ 	* {String} or {Number} The fid.
+ 	*/
+	extractFidFromField: function(field) {
+		if (!field.match(this.fidRegExp) && this.typeOfFid == "number") {
+			field = parseFloat(field);
+		}
+		return field;
+	},
+	/**
+ 	* APIMethod: create
+ 	* Create new features into the database.
+ 	*
+ 	* Parameters:
+ 	* features - {Array({<OpenLayers.Feature.Vector>})} or
+ 	*            {<OpenLayers.Feature.Vector>} The features to create in
+ 	*            the database.
+ 	* options - {Object} Optional object for configuring the request.
+ 	*
+ 	* Returns:
+ 	*  {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+ 	*          object.
+ 	*/
+	create: function(features, options) {
+		options = OpenLayers.Util.applyDefaults(options, this.options);
+
+		var resp = this.createOrUpdate(features);
+		resp.requestType = "create";
+
+		if (options && options.callback) {
+			options.callback.call(options.scope, resp);
+		}
+
+		return resp;
+	},
+	/**
+ 	* APIMethod: update
+ 	* Construct a request updating modified feature.
+ 	*
+ 	* Parameters:
+ 	* features - {Array({<OpenLayers.Feature.Vector>})} or
+ 	*            {<OpenLayers.Feature.Vector>} The features to update in
+ 	*            the database.
+ 	* options - {Object} Optional object for configuring the request.
+ 	*
+ 	* Returns:
+ 	*  {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+ 	*          object.
+ 	*/
+	update: function(features, options) {
+		options = OpenLayers.Util.applyDefaults(options, this.options);
+
+		var resp = this.createOrUpdate(features);
+		resp.requestType = "update";
+
+		if (options && options.callback) {
+			options.callback.call(options.scope, resp);
+		}
+
+		return resp;
+	},
+	/**
+ 	* Method: createOrUpdate
+ 	* Construct a request for updating or creating features in the
+ 	* database.
+ 	*
+ 	* Parameters:
+ 	* features - {Array({<OpenLayers.Feature.Vector>})} or
+ 	*      {<OpenLayers.Feature.Vector>} The feature to create or update
+ 	*      in the database.
+ 	*
+ 	* Returns:
+ 	*  {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+ 	*          object.
+ 	* untested, jgr
+ 	*/
+	createOrUpdate: function(features) {
+		if (!(features instanceof Array)) {
+			features = [features];
+		}
+
+		var i, len = features.length, feature;
+		var insertedFeatures = new Array(len);
+
+		for (i = 0; i < len; i++) {
+			feature = features[i];
+
+			var params = this.freezeFeature(feature);
+
+			this.db.transaction( function(tx) {
+			tx.executeSql("REPLACE INTO " + this.tableName + " (fid, geometry, properties, state) VALUES (?, ?, ?, ?)",
+			params,
+			function() {},
+			function() {});
+			};
+
+			var clone = feature.clone();
+			clone.fid = this.extractFidFromField(params[0]);
+			insertedFeatures[i] = clone;
+		}
+
+		return new OpenLayers.Protocol.Response({
+			code: OpenLayers.Protocol.Response.SUCCESS,
+			features: insertedFeatures,
+			reqFeatures: features
+		});
+	},
+	/**
+ 	* Method: freezeFeature
+ 	*
+ 	* Parameters:
+ 	* feature - {<OpenLayers.Feature.Vector>}
+ 	* state - {String} The feature state to store in the database.
+ 	*
+ 	* Returns:
+ 	* {Array}
+ 	*/
+	freezeFeature: function(feature) {
+		// 2 notes:
+		// - fid might not be a string
+		// - getFeatureStateForFreeze needs the feature fid to it's stored
+		//   in the feature here
+		feature.fid = feature.fid != null ?
+		"" + feature.fid : OpenLayers.Util.createUniqueID(this.FID_PREFIX);
+
+		var geometry = feature.geometry != null ?
+		feature.geometry.toString() : this.NULL_GEOMETRY;
+
+		var properties = this.jsonParser.write(feature.attributes);
+
+		var state = this.getFeatureStateForFreeze(feature);
+
+		return [feature.fid, geometry, properties, state];
+	},
+	/**
+ 	* Method: getFeatureStateForFreeze
+ 	* Get the state of the feature to store into the database.
+ 	*
+ 	* Parameters:
+ 	* feature - {<OpenLayers.Feature.Vector>} The feature.
+ 	*
+ 	* Returns
+ 	* {String} The state
+ 	*/
+	getFeatureStateForFreeze: function(feature) {
+		var state;
+		if (!this.saveFeatureState) {
+			state = this.NULL_FEATURE_STATE;
+		} else if (this.createdOffline(feature)) {
+			// if the feature was created in offline mode, its
+			// state must remain INSERT
+			state = OpenLayers.State.INSERT;
+		} else {
+			state = feature.state;
+		}
+		return state;
+	},
+	/**
+ 	* APIMethod: delete
+ 	* Delete features from the database.
+ 	*
+ 	* Parameters:
+ 	* features - {Array({<OpenLayers.Feature.Vector>})} or
+ 	*            {<OpenLayers.Feature.Vector>}
+ 	* options - {Object} Optional object for configuring the request.
+ 	*       This object is modified and should not be reused.
+ 	*
+ 	* Returns:
+ 	*  {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+ 	*          object.
+ 	*/
+	"delete": function(features, options) {
+		if (!(features instanceof Array)) {
+			features = [features];
+		}
+
+		options = OpenLayers.Util.applyDefaults(options, this.options);
+
+		var i, len, feature;
+		for (i = 0, len = features.length; i < len; i++) {
+			feature = features[i];
+
+			// if saveFeatureState is set to true and if the feature wasn't created
+			// in offline mode we don't delete it in the database but just update
+			// it state column
+			if (this.saveFeatureState && !this.createdOffline(feature)) {
+				var toDelete = feature.clone();
+				toDelete.fid = feature.fid;
+				if (toDelete.geometry) {
+					toDelete.geometry.destroy();
+					toDelete.geometry = null;
+				}
+				toDelete.state = feature.state;
+				this.createOrUpdate(toDelete);
+			} else {
+				this.db.transaction( function(tx) {
+					tx.executeSql("DELETE FROM " + this.tableName + " WHERE fid = ?", [feature.fid]);
+					// tx.executeSql('DROP TABLE summits;'); // it works! But the table needs to be recreated.
+				}, function(error) {
+					console.log('something on second function, might be an error');
+					console.debug(error.message);
+				}, function() {
+					console.log('it went well, I guess');
+				}
+				);
+
+			}
+		}
+
+		var resp = new OpenLayers.Protocol.Response({
+			code: OpenLayers.Protocol.Response.SUCCESS,
+			requestType: "delete",
+			reqFeatures: features
+		});
+
+		if (options && options.callback) {
+			options.callback.call(options.scope, resp);
+		}
+
+		return resp;
+	},
+	/**
+ 	* Method: createdOffline
+ 	* Returns true if the feature had a feature id when it was created in
+ 	*      the Gears database, false otherwise; this is determined by
+ 	*      checking the form of the feature's fid value.
+ 	*
+ 	* Parameters:
+ 	* feature - {<OpenLayers.Feature.Vector>}
+ 	*
+ 	* Returns:
+ 	* {Boolean}
+ 	*/
+	createdOffline: function(feature) {
+		return (typeof feature.fid == "string" &&
+			!!(feature.fid.match(this.fidRegExp)));
+	},
+	/**
+ 	* APIMethod: commit
+ 	* Go over the features and for each take action
+ 	* based on the feature state. Possible actions are create,
+ 	* update and delete.
+ 	*
+ 	* Parameters:
+ 	* features - {Array({<OpenLayers.Feature.Vector>})}
+ 	* options - {Object} Object whose possible keys are "create", "update",
+ 	*      "delete", "callback" and "scope", the values referenced by the
+ 	*      first three are objects as passed to the "create", "update", and
+ 	*      "delete" methods, the value referenced by the "callback" key is
+ 	*      a function which is called when the commit operation is complete
+ 	*      using the scope referenced by the "scope" key.
+ 	*
+ 	* Returns:
+ 	* {Array({<OpenLayers.Protocol.Response>})} An array of
+ 	*       <OpenLayers.Protocol.Response> objects, one per request made
+ 	*       to the database.
+ 	*/
+	commit: function(features, options) {
+		var opt, resp = [], nRequests = 0, nResponses = 0;
+
+		function callback(resp) {
+			if (++nResponses < nRequests) {
+				resp.last = false;
+			}
+			this.callUserCallback(options, resp);
+		}
+
+		var feature, toCreate = [], toUpdate = [], toDelete = [];
+		for (var i = features.length - 1; i >= 0; i--) {
+			feature = features[i];
+			switch (feature.state) {
+				case OpenLayers.State.INSERT:
+					toCreate.push(feature);
+					break;
+				case OpenLayers.State.UPDATE:
+					toUpdate.push(feature);
+					break;
+				case OpenLayers.State.DELETE:
+					toDelete.push(feature);
+					break;
+			}
+		}
+		if (toCreate.length > 0) {
+			nRequests++;
+			opt = OpenLayers.Util.applyDefaults(
+			{"callback": callback, "scope": this},
+			options.create
+			);
+			resp.push(this.create(toCreate, opt));
+		}
+		if (toUpdate.length > 0) {
+			nRequests++;
+			opt = OpenLayers.Util.applyDefaults(
+			{"callback": callback, "scope": this},
+			options.update
+			);
+			resp.push(this.update(toUpdate, opt));
+		}
+		if (toDelete.length > 0) {
+			nRequests++;
+			opt = OpenLayers.Util.applyDefaults(
+			{"callback": callback, "scope": this},
+			options["delete"]
+			);
+			resp.push(this["delete"](toDelete, opt));
+		}
+
+		return resp;
+	},
+	/**
+ 	* Method: clear
+ 	* Removes all rows of the table.
+ 	* untested, jgr
+ 	*/
+	clear: function() {
+		this.db.execute("DELETE FROM " + this.tableName);
+
+		this.db.transaction( function(tx) {
+			tx.executeSql('delete from ' + this.tableName);
+			// tx.executeSql('DROP TABLE ' + this.tableName); // it works! But the table needs to be recreated.
+		}, function(error) {
+			console.log('might be an error: ' +  error);
+			console.debug(error.message);
+		}, function() {
+			console.log('it went well, I guess');
+		}
+		);
+	},
+	/**
+ 	* Method: callUserCallback
+ 	* This method is called from within commit each time a request is made
+ 	* to the database, it is responsible for calling the user-supplied
+ 	* callbacks.
+ 	*
+ 	* Parameters:
+ 	* options - {Object} The map of options passed to the commit call.
+ 	* resp - {<OpenLayers.Protocol.Response>}
+ 	*/
+	callUserCallback: function(options, resp) {
+		var opt = options[resp.requestType];
+		if (opt && opt.callback) {
+			opt.callback.call(opt.scope, resp);
+		}
+		if (resp.last && options.callback) {
+			options.callback.call(options.scope);
+		}
+	},
+	CLASS_NAME: "OpenLayers.Protocol.SQL.LocalSQL"
+});



More information about the Commits mailing list