1st version w/ no errors.

This commit is contained in:
Andy Gup 2015-02-23 14:35:59 -07:00
parent e6b3150349
commit ccb93afb4f
5 changed files with 459 additions and 571 deletions

File diff suppressed because one or more lines are too long

View File

@ -79,47 +79,6 @@ define([
}
},
/**
* internal method that checks if this browser supports everything that is needed to handle offline attachments
* it also extends XMLHttpRequest with sendAsBinary() method, needed in Chrome
*/
_checkFileAPIs: function()
{
if( window.File && window.FileReader && window.FileList && window.Blob )
{
console.log("All APIs supported!");
if(!XMLHttpRequest.prototype.sendAsBinary )
{
// https://code.google.com/p/chromium/issues/detail?id=35705#c40
XMLHttpRequest.prototype.sendAsBinary = function(datastr)
{
function byteValue(x) {
return x.charCodeAt(0) & 0xff;
}
var ords = Array.prototype.map.call(datastr, byteValue);
var ui8a = new Uint8Array(ords);
this.send(ui8a.buffer);
};
console.log("extending XMLHttpRequest");
}
return true;
}
console.log("The File APIs are not fully supported in this browser.");
return false;
},
/**
* internal method that extends an object with sendAsBinary() method
* sometimes extending XMLHttpRequest.prototype is not enough, as ArcGIS JS lib seems to mess with this object too
* @param oAjaxReq object to extend
*/
_extendAjaxReq: function(oAjaxReq)
{
oAjaxReq.sendAsBinary = XMLHttpRequest.prototype.sendAsBinary;
console.log("extending XMLHttpRequest");
},
/**
* Overrides a feature layer.
* @param layer
@ -132,7 +91,7 @@ define([
// Attempt to initialize the database
self._editStore.init(function(result){
callback(result);
return;
//return;
});
// we keep track of the FeatureLayer object
@ -434,7 +393,7 @@ define([
},this);
all(promises).then( function(r)
{ console.log("DONE WITH DATABASE PUSH");
{
//TO-DO - handle information related to any failed edits that didn't get stored
/* we already pushed the edits into the database, now we let the FeatureLayer to do the local updating of the layer graphics */
@ -648,25 +607,48 @@ define([
return this._onlineStatus;
},
/* internal methods */
/**
* A string value representing human readable information on pending edits
* @param edit
* @returns {string}
* internal method that checks if this browser supports everything that is needed to handle offline attachments
* it also extends XMLHttpRequest with sendAsBinary() method, needed in Chrome
*/
getReadableEdit: function(edit)
_checkFileAPIs: function()
{
var layer = this._featureLayers[ edit.layer ];
var graphic = this._editStore._deserialize(edit.graphic);
var readableGraphic = graphic.geometry.type;
var layerId = edit.layer.substring(edit.layer.lastIndexOf("/")+1);
if(layer)
if( window.File && window.FileReader && window.FileList && window.Blob )
{
readableGraphic += " [id=" + graphic.attributes[layer.objectIdField] + "]";
console.log("All APIs supported!");
if(!XMLHttpRequest.prototype.sendAsBinary )
{
// https://code.google.com/p/chromium/issues/detail?id=35705#c40
XMLHttpRequest.prototype.sendAsBinary = function(datastr)
{
function byteValue(x) {
return x.charCodeAt(0) & 0xff;
}
var ords = Array.prototype.map.call(datastr, byteValue);
var ui8a = new Uint8Array(ords);
this.send(ui8a.buffer);
};
console.log("extending XMLHttpRequest");
}
return true;
}
return "o:" + edit.operation + ", l:" + layerId + ", g:" + readableGraphic;
console.log("The File APIs are not fully supported in this browser.");
return false;
},
/* internal methods */
/**
* internal method that extends an object with sendAsBinary() method
* sometimes extending XMLHttpRequest.prototype is not enough, as ArcGIS JS lib seems to mess with this object too
* @param oAjaxReq object to extend
*/
_extendAjaxReq: function(oAjaxReq)
{
oAjaxReq.sendAsBinary = XMLHttpRequest.prototype.sendAsBinary;
console.log("extending XMLHttpRequest");
},
//
// phantom symbols
@ -864,6 +846,171 @@ define([
// methods to send features back to the server
//
_replayStoredEdits: function(callback)
{
var promises = {};
var that = this;
//
// send edits for each of the layers
//
var layer;
var adds = [], updates = [], deletes = [];
var tempObjectIds = [];
var tempArray = [];
var featureLayers = this._featureLayers;
var attachmentsStore = this.attachmentsStore;
var editStore = this._editStore;
this._editStore.getAllEditsArray(function(result,err){
if(result != null) {
tempArray = result;
var length = tempArray.length;
for(var n= 0;n < length;n++) {
layer = featureLayers[tempArray[n].layer];
// If the layer has attachments then check to see if the attachmentsStore has been initialized
if (attachmentsStore == null && layer.hasAttachments) {
console.log("ERROR: you need to run OfflineFeaturesManager.initAttachments(). Check the Attachments doc for more info.")
throw new Error("OfflineFeaturesManager: Attachments aren't initialized.");
}
// Assign the attachmentsStore to the layer as a private var so we can access it from
// the promises applyEdits() method.
layer._attachmentsStore = attachmentsStore;
layer.__onEditsComplete = layer.onEditsComplete;
layer.onEditsComplete = function () {
console.log("intercepting events onEditsComplete");
};
layer.__onBeforeApplyEdits = layer.onBeforeApplyEdits;
layer.onBeforeApplyEdits = function () {
console.log("intercepting events onBeforeApplyEdits");
};
adds = [], updates = [], deletes = [], tempObjectIds = [];
// IMPORTANT: reconstitute the graphic JSON into an actual esri.Graphic object
var graphic = new Graphic(JSON.parse(tempArray[n].graphic));
switch (tempArray[n].operation) {
case editStore.ADD:
for (var i = 0; i < layer.graphics.length; i++) {
var g = layer.graphics[i];
if (g.attributes[layer.objectIdField] === graphic.attributes[layer.objectIdField]) {
layer.remove(g);
break;
}
}
tempObjectIds.push(graphic.attributes[layer.objectIdField]);
delete graphic.attributes[layer.objectIdField];
adds.push(graphic);
break;
case editStore.UPDATE:
updates.push(graphic);
break;
case editStore.DELETE:
deletes.push(graphic);
break;
}
promises[n] = that._internalApplyEdits(layer, tempObjectIds, adds, updates, deletes);
}
}
// wait for all requests to finish
//
var allPromises = all(promises);
allPromises.then(
function(responses)
{
console.log("OfflineFeaturesManager - all responses are back");
this._cleanDatabase(responses);
this.emit(this.events.EDITS_SENT);
this.emit(this.events.ALL_EDITS_SENT);
callback && callback(true,responses);
}.bind(that),
function(errors)
{
console.log("OfflineFeaturesManager - ERROR!!");
console.log(errors);
callback && callback(false,errors);
}.bind(that)
);
});
},
_cleanDatabase: function(responses){
if( Object.keys(responses).length !== 0 ){
for(var key in responses){
if (responses.hasOwnProperty(key)) {
console.log("KEY " + key);
}
}
}
},
/**
* Executes the _applyEdits() method
* @param layer
* @param tempObjectIds
* @param adds
* @param updates
* @param deletes
* @returns {l.Deferred.promise|*|c.promise|q.promise|promise}
* @private
*/
_internalApplyEdits: function(layer,tempObjectIds,adds,updates,deletes)
{
var dfd = new Deferred();
layer._applyEdits(adds,updates,deletes,
function(addResults,updateResults,deleteResults)
{
layer._phantomLayer.clear();
layer.onBeforeApplyEdits = layer.__onBeforeApplyEdits;
delete layer.__onBeforeApplyEdits;
var newObjectIds = addResults.map(function (r) {
return r.objectId;
});
// We use a different pattern if the attachmentsStore is valid and the layer has attachments
if (layer._attachmentsStore != null && layer.hasAttachments && tempObjectIds.length > 0) {
layer._replaceFeatureIds(tempObjectIds, newObjectIds, function (success) {
dfd.resolve({
addResults: addResults,
updateResults: updateResults,
deleteResults: deleteResults
}); // wrap three arguments in a single object
});
}
else {
dfd.resolve({
addResults: addResults,
updateResults: updateResults,
deleteResults: deleteResults
}); // wrap three arguments in a single object
}
},
function(error)
{
layer.onEditsComplete = layer.__onEditsComplete; delete layer.__onEditsComplete;
layer.onBeforeApplyEdits = layer.__onBeforeApplyEdits; delete layer.__onBeforeApplyEdits;
dfd.reject(error);
}
);
return dfd.promise;
},
/**
* DEPRECATED @ v2.5
* @returns {{}}
* @private
*/
_optimizeEditsQueue: function()
{
var optimizedEdits = {},
@ -926,227 +1073,23 @@ define([
return optimizedEdits;
},
_internalApplyEdits: function(layer,tempObjectIds,adds,updates,deletes)
/**
* DEPRECATED @ v2.5
* A string value representing human readable information on pending edits
* @param edit
* @returns {string}
*/
getReadableEdit: function(edit)
{
// unfortunately we can't use the promise that is returned from layer._applyEdits()
// because it returns 3 result parameters (addResults,updateResults,deleteResults)
// and when we combine all promises in the dojo/promise/all() method below this only
// supports promises that return one value
var dfd = new Deferred();
console.log("PRE APPLYEDITS " + adds + ", " + updates + ", " + deletes);
var internalLayer = layer;
internalLayer.dfd;
internalLayer._applyEdits(adds,updates,deletes,
function(addResults,updateResults,deleteResults)
{ console.log("RUNNNING APPLY EDITS")
try {
internalLayer._phantomLayer.clear();
internalLayer.onEditsComplete = internalLayer.__onEditsComplete;
delete internalLayer.__onEditsComplete;
internalLayer.onBeforeApplyEdits = internalLayer.__onBeforeApplyEdits;
delete internalLayer.__onBeforeApplyEdits;
var newObjectIds = addResults.map(function (r) {
return r.objectId;
});
console.log("INTERNAL " + addResults + ", update " + updateResults + ", delete " + deleteResults)
// We use a different pattern if the attachmentsStore is valid and the layer has attachments
if (internalLayer._attachmentsStore != null && internalLayer.hasAttachments && tempObjectIds.length > 0) {
internalLayer._replaceFeatureIds(tempObjectIds, newObjectIds, function (success) {
dfd.resolve({
addResults: addResults,
updateResults: updateResults,
deleteResults: deleteResults
}); // wrap three arguments in a single object
});
}
else {
dfd.resolve({
addResults: addResults,
updateResults: updateResults,
deleteResults: deleteResults
}); // wrap three arguments in a single object
}
}catch(err){
console.log("ERROR ERROR " + err);
}
},
function(error)
{ console.log("INTERNAL ERROR " + adds + ", update " + JSON.stringify(updates) + ", delete " + deletes + ", " + JSON.stringify(error))
internalLayer.onEditsComplete = internalLayer.__onEditsComplete; delete internalLayer.__onEditsComplete;
internalLayer.onBeforeApplyEdits = internalLayer.__onBeforeApplyEdits; delete internalLayer.__onBeforeApplyEdits;
dfd.reject(error);
}
);
return dfd;
},
_replayStoredEdits: function(callback)
{
var promises = {};
var deferredListArr = [];
var that = this;
//
// send edits for each of the layers
//
var layerUrl, layer, layerEdits;
var adds, updates, deletes;
var tempObjectIds;
var objectId, c= 1000;
var i,g;
var tempArray = [];
var featureLayers = this._featureLayers;
var attachmentsStore = this.attachmentsStore;
var editStore = this._editStore;
this._editStore.getAllEditsArray(function(result,err){
if(result != null) {
tempArray = result;
//}
//else {
var length = tempArray.length;
//length = 9;
for(var n= 0;n < length;n++) {
layer = featureLayers[tempArray[n].layer];
// If the layer has attachments then check to see if the attachmentsStore has been initialized
if (attachmentsStore == null && layer.hasAttachments) {
console.log("ERROR: you need to run OfflineFeaturesManager.initAttachments(). Check the Attachments doc for more info.")
throw new Error("OfflineFeaturesManager: Attachments aren't initialized.");
}
// Assign the attachmentsStore to the layer as a private var so we can access it from
// the promises applyEdits() method.
layer._attachmentsStore = attachmentsStore;
//layerEdits = optimizedEdits[layerUrl];
//
//console.assert(Object.keys(layerEdits).length !== 0);
layer.__onEditsComplete = layer.onEditsComplete;
layer.onEditsComplete = function () {
console.log("intercepting events onEditsComplete");
};
layer.__onBeforeApplyEdits = layer.onBeforeApplyEdits;
layer.onBeforeApplyEdits = function () {
console.log("intercepting events onBeforeApplyEdits");
};
adds = [];
updates = [];
deletes = [];
tempObjectIds = [];
// IMPORTANT: we have to reconstitute the graphic JSON into an actual esri.Graphic object
var graphic = new Graphic(JSON.parse(tempArray[n].graphic));
switch (tempArray[n].operation) {
case editStore.ADD:
for (i = 0; i < layer.graphics.length; i++) {
g = layer.graphics[i];
if (g.attributes[layer.objectIdField] === graphic.attributes[layer.objectIdField]) {
layer.remove(g);
break;
}
}
tempObjectIds.push(graphic.attributes[layer.objectIdField]);
delete graphic.attributes[layer.objectIdField];
adds.push(graphic);
break;
case editStore.UPDATE:
updates.push(graphic);
break;
case editStore.DELETE:
deletes.push(graphic);
break;
}
console.log("TEST " + layer + ", ids " + tempObjectIds + ", adds " + adds + ", updates " + updates + ", deletes " + deletes)
console.log("COUNT " + n);
//setTimeout(function()
//{
// promises[n] = that._internalApplyEdits(layer, tempObjectIds, adds, updates, deletes);
deferredListArr.push(that._internalApplyEdits(layer, tempObjectIds, adds, updates, deletes));
//deferredListArr.push(test(layer, tempObjectIds, adds, updates, deletes));
//}.bind(this),c++);
//// closure to keep layer and tempObjectIds values
//promises[n] = function(layer,tempObjectIds)
//{
// // unfortunately we can't use the promise that is returned from layer._applyEdits()
// // because it returns 3 result parameters (addResults,updateResults,deleteResults)
// // and when we combine all promises in the dojo/promise/all() method below this only
// // supports promises that return one value
// var dfd = new Deferred();
// promises[n] = layer._applyEdits(adds,updates,deletes,
// function(addResults,updateResults,deleteResults)
// {
// layer._phantomLayer.clear();
// layer.onEditsComplete = layer.__onEditsComplete; delete layer.__onEditsComplete;
// layer.onBeforeApplyEdits = layer.__onBeforeApplyEdits; delete layer.__onBeforeApplyEdits;
// var newObjectIds = addResults.map(function(r){ return r.objectId; });
//
// // We use a different pattern if the attachmentsStore is valid and the layer has attachments
// if( layer._attachmentsStore != null && layer.hasAttachments && tempObjectIds.length > 0)
// {
// layer._replaceFeatureIds(tempObjectIds,newObjectIds,function(success)
// {
// dfd.resolve({addResults:addResults,updateResults:updateResults,deleteResults:deleteResults}); // wrap three arguments in a single object
// });
// }
// else
// {
// dfd.resolve({addResults:addResults,updateResults:updateResults,deleteResults:deleteResults}); // wrap three arguments in a single object
// }
// },
// function(error)
// {
// layer.onEditsComplete = layer.__onEditsComplete; delete layer.__onEditsComplete;
// layer.onBeforeApplyEdits = layer.__onBeforeApplyEdits; delete layer.__onBeforeApplyEdits;
// dfd.reject(error);
// }
// );
// return dfd;
//}(layer,tempObjectIds);
if(n == length - 1) console.log("DONE with loop " )
}
}
//return all(promises);
// wait for all requests to finish
//
var allPromises = all(promises);
var deferredList = new DeferredList(deferredListArr);
deferredList.then(
function(responses)
{
console.log("all responses are back");
//this.emit(this.events.EDITS_SENT);
//this.emit(this.events.ALL_EDITS_SENT);
callback && callback(true,responses);
}.bind(self),
function(errors)
{
console.log("ERROR!!");
console.log(errors);
callback && callback(false,errors);
}.bind(this)
);
});
var layer = this._featureLayers[ edit.layer ];
var graphic = this._editStore._deserialize(edit.graphic);
var readableGraphic = graphic.geometry.type;
var layerId = edit.layer.substring(edit.layer.lastIndexOf("/")+1);
if(layer)
{
readableGraphic += " [id=" + graphic.attributes[layer.objectIdField] + "]";
}
return "o:" + edit.operation + ", l:" + layerId + ", g:" + readableGraphic;
}
}); // declare
@ -1530,19 +1473,23 @@ O.esri.Edit.EditStore = function()
// internal methods
//
// graphic serialization/deserialization
//
/**
* Save space in the database...don't need to store the entire Graphic object just its public properties!
* @param graphic
* @returns {*}
* @private
*/
this._serialize = function(graphic)
{
// keep only attributes and geometry, that are the values that get sent to the server by applyEdits()
// see http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Apply_Edits_Feature_Service_Layer/02r3000000r6000000/
// use graphic's built-in serializing method
var json = graphic.toJson();
var jsonClean =
{
attributes: json.attributes,
geometry: json.geometry
geometry: json.geometry,
infoTemplate: json.infoTemplate,
symbol: json.symbol
};
return JSON.stringify(jsonClean);
};

View File

@ -359,19 +359,23 @@ O.esri.Edit.EditStore = function()
// internal methods
//
// graphic serialization/deserialization
//
/**
* Save space in the database...don't need to store the entire Graphic object just its public properties!
* @param graphic
* @returns {*}
* @private
*/
this._serialize = function(graphic)
{
// keep only attributes and geometry, that are the values that get sent to the server by applyEdits()
// see http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Apply_Edits_Feature_Service_Layer/02r3000000r6000000/
// use graphic's built-in serializing method
var json = graphic.toJson();
var jsonClean =
{
attributes: json.attributes,
geometry: json.geometry
geometry: json.geometry,
infoTemplate: json.infoTemplate,
symbol: json.symbol
};
return JSON.stringify(jsonClean);
};

View File

@ -76,47 +76,6 @@ define([
}
},
/**
* internal method that checks if this browser supports everything that is needed to handle offline attachments
* it also extends XMLHttpRequest with sendAsBinary() method, needed in Chrome
*/
_checkFileAPIs: function()
{
if( window.File && window.FileReader && window.FileList && window.Blob )
{
console.log("All APIs supported!");
if(!XMLHttpRequest.prototype.sendAsBinary )
{
// https://code.google.com/p/chromium/issues/detail?id=35705#c40
XMLHttpRequest.prototype.sendAsBinary = function(datastr)
{
function byteValue(x) {
return x.charCodeAt(0) & 0xff;
}
var ords = Array.prototype.map.call(datastr, byteValue);
var ui8a = new Uint8Array(ords);
this.send(ui8a.buffer);
};
console.log("extending XMLHttpRequest");
}
return true;
}
console.log("The File APIs are not fully supported in this browser.");
return false;
},
/**
* internal method that extends an object with sendAsBinary() method
* sometimes extending XMLHttpRequest.prototype is not enough, as ArcGIS JS lib seems to mess with this object too
* @param oAjaxReq object to extend
*/
_extendAjaxReq: function(oAjaxReq)
{
oAjaxReq.sendAsBinary = XMLHttpRequest.prototype.sendAsBinary;
console.log("extending XMLHttpRequest");
},
/**
* Overrides a feature layer.
* @param layer
@ -129,7 +88,7 @@ define([
// Attempt to initialize the database
self._editStore.init(function(result){
callback(result);
return;
//return;
});
// we keep track of the FeatureLayer object
@ -431,7 +390,7 @@ define([
},this);
all(promises).then( function(r)
{ console.log("DONE WITH DATABASE PUSH");
{
//TO-DO - handle information related to any failed edits that didn't get stored
/* we already pushed the edits into the database, now we let the FeatureLayer to do the local updating of the layer graphics */
@ -645,25 +604,48 @@ define([
return this._onlineStatus;
},
/* internal methods */
/**
* A string value representing human readable information on pending edits
* @param edit
* @returns {string}
* internal method that checks if this browser supports everything that is needed to handle offline attachments
* it also extends XMLHttpRequest with sendAsBinary() method, needed in Chrome
*/
getReadableEdit: function(edit)
_checkFileAPIs: function()
{
var layer = this._featureLayers[ edit.layer ];
var graphic = this._editStore._deserialize(edit.graphic);
var readableGraphic = graphic.geometry.type;
var layerId = edit.layer.substring(edit.layer.lastIndexOf("/")+1);
if(layer)
if( window.File && window.FileReader && window.FileList && window.Blob )
{
readableGraphic += " [id=" + graphic.attributes[layer.objectIdField] + "]";
console.log("All APIs supported!");
if(!XMLHttpRequest.prototype.sendAsBinary )
{
// https://code.google.com/p/chromium/issues/detail?id=35705#c40
XMLHttpRequest.prototype.sendAsBinary = function(datastr)
{
function byteValue(x) {
return x.charCodeAt(0) & 0xff;
}
var ords = Array.prototype.map.call(datastr, byteValue);
var ui8a = new Uint8Array(ords);
this.send(ui8a.buffer);
};
console.log("extending XMLHttpRequest");
}
return true;
}
return "o:" + edit.operation + ", l:" + layerId + ", g:" + readableGraphic;
console.log("The File APIs are not fully supported in this browser.");
return false;
},
/* internal methods */
/**
* internal method that extends an object with sendAsBinary() method
* sometimes extending XMLHttpRequest.prototype is not enough, as ArcGIS JS lib seems to mess with this object too
* @param oAjaxReq object to extend
*/
_extendAjaxReq: function(oAjaxReq)
{
oAjaxReq.sendAsBinary = XMLHttpRequest.prototype.sendAsBinary;
console.log("extending XMLHttpRequest");
},
//
// phantom symbols
@ -861,6 +843,171 @@ define([
// methods to send features back to the server
//
_replayStoredEdits: function(callback)
{
var promises = {};
var that = this;
//
// send edits for each of the layers
//
var layer;
var adds = [], updates = [], deletes = [];
var tempObjectIds = [];
var tempArray = [];
var featureLayers = this._featureLayers;
var attachmentsStore = this.attachmentsStore;
var editStore = this._editStore;
this._editStore.getAllEditsArray(function(result,err){
if(result != null) {
tempArray = result;
var length = tempArray.length;
for(var n= 0;n < length;n++) {
layer = featureLayers[tempArray[n].layer];
// If the layer has attachments then check to see if the attachmentsStore has been initialized
if (attachmentsStore == null && layer.hasAttachments) {
console.log("ERROR: you need to run OfflineFeaturesManager.initAttachments(). Check the Attachments doc for more info.")
throw new Error("OfflineFeaturesManager: Attachments aren't initialized.");
}
// Assign the attachmentsStore to the layer as a private var so we can access it from
// the promises applyEdits() method.
layer._attachmentsStore = attachmentsStore;
layer.__onEditsComplete = layer.onEditsComplete;
layer.onEditsComplete = function () {
console.log("intercepting events onEditsComplete");
};
layer.__onBeforeApplyEdits = layer.onBeforeApplyEdits;
layer.onBeforeApplyEdits = function () {
console.log("intercepting events onBeforeApplyEdits");
};
adds = [], updates = [], deletes = [], tempObjectIds = [];
// IMPORTANT: reconstitute the graphic JSON into an actual esri.Graphic object
var graphic = new Graphic(JSON.parse(tempArray[n].graphic));
switch (tempArray[n].operation) {
case editStore.ADD:
for (var i = 0; i < layer.graphics.length; i++) {
var g = layer.graphics[i];
if (g.attributes[layer.objectIdField] === graphic.attributes[layer.objectIdField]) {
layer.remove(g);
break;
}
}
tempObjectIds.push(graphic.attributes[layer.objectIdField]);
delete graphic.attributes[layer.objectIdField];
adds.push(graphic);
break;
case editStore.UPDATE:
updates.push(graphic);
break;
case editStore.DELETE:
deletes.push(graphic);
break;
}
promises[n] = that._internalApplyEdits(layer, tempObjectIds, adds, updates, deletes);
}
}
// wait for all requests to finish
//
var allPromises = all(promises);
allPromises.then(
function(responses)
{
console.log("OfflineFeaturesManager - all responses are back");
this._cleanDatabase(responses);
this.emit(this.events.EDITS_SENT);
this.emit(this.events.ALL_EDITS_SENT);
callback && callback(true,responses);
}.bind(that),
function(errors)
{
console.log("OfflineFeaturesManager - ERROR!!");
console.log(errors);
callback && callback(false,errors);
}.bind(that)
);
});
},
_cleanDatabase: function(responses){
if( Object.keys(responses).length !== 0 ){
for(var key in responses){
if (responses.hasOwnProperty(key)) {
console.log("KEY " + key);
}
}
}
},
/**
* Executes the _applyEdits() method
* @param layer
* @param tempObjectIds
* @param adds
* @param updates
* @param deletes
* @returns {l.Deferred.promise|*|c.promise|q.promise|promise}
* @private
*/
_internalApplyEdits: function(layer,tempObjectIds,adds,updates,deletes)
{
var dfd = new Deferred();
layer._applyEdits(adds,updates,deletes,
function(addResults,updateResults,deleteResults)
{
layer._phantomLayer.clear();
layer.onBeforeApplyEdits = layer.__onBeforeApplyEdits;
delete layer.__onBeforeApplyEdits;
var newObjectIds = addResults.map(function (r) {
return r.objectId;
});
// We use a different pattern if the attachmentsStore is valid and the layer has attachments
if (layer._attachmentsStore != null && layer.hasAttachments && tempObjectIds.length > 0) {
layer._replaceFeatureIds(tempObjectIds, newObjectIds, function (success) {
dfd.resolve({
addResults: addResults,
updateResults: updateResults,
deleteResults: deleteResults
}); // wrap three arguments in a single object
});
}
else {
dfd.resolve({
addResults: addResults,
updateResults: updateResults,
deleteResults: deleteResults
}); // wrap three arguments in a single object
}
},
function(error)
{
layer.onEditsComplete = layer.__onEditsComplete; delete layer.__onEditsComplete;
layer.onBeforeApplyEdits = layer.__onBeforeApplyEdits; delete layer.__onBeforeApplyEdits;
dfd.reject(error);
}
);
return dfd.promise;
},
/**
* DEPRECATED @ v2.5
* @returns {{}}
* @private
*/
_optimizeEditsQueue: function()
{
var optimizedEdits = {},
@ -923,227 +1070,23 @@ define([
return optimizedEdits;
},
_internalApplyEdits: function(layer,tempObjectIds,adds,updates,deletes)
/**
* DEPRECATED @ v2.5
* A string value representing human readable information on pending edits
* @param edit
* @returns {string}
*/
getReadableEdit: function(edit)
{
// unfortunately we can't use the promise that is returned from layer._applyEdits()
// because it returns 3 result parameters (addResults,updateResults,deleteResults)
// and when we combine all promises in the dojo/promise/all() method below this only
// supports promises that return one value
var dfd = new Deferred();
console.log("PRE APPLYEDITS " + adds + ", " + updates + ", " + deletes);
var internalLayer = layer;
internalLayer.dfd;
internalLayer._applyEdits(adds,updates,deletes,
function(addResults,updateResults,deleteResults)
{ console.log("RUNNNING APPLY EDITS")
try {
internalLayer._phantomLayer.clear();
internalLayer.onEditsComplete = internalLayer.__onEditsComplete;
delete internalLayer.__onEditsComplete;
internalLayer.onBeforeApplyEdits = internalLayer.__onBeforeApplyEdits;
delete internalLayer.__onBeforeApplyEdits;
var newObjectIds = addResults.map(function (r) {
return r.objectId;
});
console.log("INTERNAL " + addResults + ", update " + updateResults + ", delete " + deleteResults)
// We use a different pattern if the attachmentsStore is valid and the layer has attachments
if (internalLayer._attachmentsStore != null && internalLayer.hasAttachments && tempObjectIds.length > 0) {
internalLayer._replaceFeatureIds(tempObjectIds, newObjectIds, function (success) {
dfd.resolve({
addResults: addResults,
updateResults: updateResults,
deleteResults: deleteResults
}); // wrap three arguments in a single object
});
}
else {
dfd.resolve({
addResults: addResults,
updateResults: updateResults,
deleteResults: deleteResults
}); // wrap three arguments in a single object
}
}catch(err){
console.log("ERROR ERROR " + err);
}
},
function(error)
{ console.log("INTERNAL ERROR " + adds + ", update " + JSON.stringify(updates) + ", delete " + deletes + ", " + JSON.stringify(error))
internalLayer.onEditsComplete = internalLayer.__onEditsComplete; delete internalLayer.__onEditsComplete;
internalLayer.onBeforeApplyEdits = internalLayer.__onBeforeApplyEdits; delete internalLayer.__onBeforeApplyEdits;
dfd.reject(error);
}
);
return dfd;
},
_replayStoredEdits: function(callback)
{
var promises = {};
var deferredListArr = [];
var that = this;
//
// send edits for each of the layers
//
var layerUrl, layer, layerEdits;
var adds, updates, deletes;
var tempObjectIds;
var objectId, c= 1000;
var i,g;
var tempArray = [];
var featureLayers = this._featureLayers;
var attachmentsStore = this.attachmentsStore;
var editStore = this._editStore;
this._editStore.getAllEditsArray(function(result,err){
if(result != null) {
tempArray = result;
//}
//else {
var length = tempArray.length;
//length = 9;
for(var n= 0;n < length;n++) {
layer = featureLayers[tempArray[n].layer];
// If the layer has attachments then check to see if the attachmentsStore has been initialized
if (attachmentsStore == null && layer.hasAttachments) {
console.log("ERROR: you need to run OfflineFeaturesManager.initAttachments(). Check the Attachments doc for more info.")
throw new Error("OfflineFeaturesManager: Attachments aren't initialized.");
}
// Assign the attachmentsStore to the layer as a private var so we can access it from
// the promises applyEdits() method.
layer._attachmentsStore = attachmentsStore;
//layerEdits = optimizedEdits[layerUrl];
//
//console.assert(Object.keys(layerEdits).length !== 0);
layer.__onEditsComplete = layer.onEditsComplete;
layer.onEditsComplete = function () {
console.log("intercepting events onEditsComplete");
};
layer.__onBeforeApplyEdits = layer.onBeforeApplyEdits;
layer.onBeforeApplyEdits = function () {
console.log("intercepting events onBeforeApplyEdits");
};
adds = [];
updates = [];
deletes = [];
tempObjectIds = [];
// IMPORTANT: we have to reconstitute the graphic JSON into an actual esri.Graphic object
var graphic = new Graphic(JSON.parse(tempArray[n].graphic));
switch (tempArray[n].operation) {
case editStore.ADD:
for (i = 0; i < layer.graphics.length; i++) {
g = layer.graphics[i];
if (g.attributes[layer.objectIdField] === graphic.attributes[layer.objectIdField]) {
layer.remove(g);
break;
}
}
tempObjectIds.push(graphic.attributes[layer.objectIdField]);
delete graphic.attributes[layer.objectIdField];
adds.push(graphic);
break;
case editStore.UPDATE:
updates.push(graphic);
break;
case editStore.DELETE:
deletes.push(graphic);
break;
}
console.log("TEST " + layer + ", ids " + tempObjectIds + ", adds " + adds + ", updates " + updates + ", deletes " + deletes)
console.log("COUNT " + n);
//setTimeout(function()
//{
// promises[n] = that._internalApplyEdits(layer, tempObjectIds, adds, updates, deletes);
deferredListArr.push(that._internalApplyEdits(layer, tempObjectIds, adds, updates, deletes));
//deferredListArr.push(test(layer, tempObjectIds, adds, updates, deletes));
//}.bind(this),c++);
//// closure to keep layer and tempObjectIds values
//promises[n] = function(layer,tempObjectIds)
//{
// // unfortunately we can't use the promise that is returned from layer._applyEdits()
// // because it returns 3 result parameters (addResults,updateResults,deleteResults)
// // and when we combine all promises in the dojo/promise/all() method below this only
// // supports promises that return one value
// var dfd = new Deferred();
// promises[n] = layer._applyEdits(adds,updates,deletes,
// function(addResults,updateResults,deleteResults)
// {
// layer._phantomLayer.clear();
// layer.onEditsComplete = layer.__onEditsComplete; delete layer.__onEditsComplete;
// layer.onBeforeApplyEdits = layer.__onBeforeApplyEdits; delete layer.__onBeforeApplyEdits;
// var newObjectIds = addResults.map(function(r){ return r.objectId; });
//
// // We use a different pattern if the attachmentsStore is valid and the layer has attachments
// if( layer._attachmentsStore != null && layer.hasAttachments && tempObjectIds.length > 0)
// {
// layer._replaceFeatureIds(tempObjectIds,newObjectIds,function(success)
// {
// dfd.resolve({addResults:addResults,updateResults:updateResults,deleteResults:deleteResults}); // wrap three arguments in a single object
// });
// }
// else
// {
// dfd.resolve({addResults:addResults,updateResults:updateResults,deleteResults:deleteResults}); // wrap three arguments in a single object
// }
// },
// function(error)
// {
// layer.onEditsComplete = layer.__onEditsComplete; delete layer.__onEditsComplete;
// layer.onBeforeApplyEdits = layer.__onBeforeApplyEdits; delete layer.__onBeforeApplyEdits;
// dfd.reject(error);
// }
// );
// return dfd;
//}(layer,tempObjectIds);
if(n == length - 1) console.log("DONE with loop " )
}
}
//return all(promises);
// wait for all requests to finish
//
var allPromises = all(promises);
var deferredList = new DeferredList(deferredListArr);
deferredList.then(
function(responses)
{
console.log("all responses are back");
//this.emit(this.events.EDITS_SENT);
//this.emit(this.events.ALL_EDITS_SENT);
callback && callback(true,responses);
}.bind(self),
function(errors)
{
console.log("ERROR!!");
console.log(errors);
callback && callback(false,errors);
}.bind(this)
);
});
var layer = this._featureLayers[ edit.layer ];
var graphic = this._editStore._deserialize(edit.graphic);
var readableGraphic = graphic.geometry.type;
var layerId = edit.layer.substring(edit.layer.lastIndexOf("/")+1);
if(layer)
{
readableGraphic += " [id=" + graphic.attributes[layer.objectIdField] + "]";
}
return "o:" + edit.operation + ", l:" + layerId + ", g:" + readableGraphic;
}
}); // declare

View File

@ -512,12 +512,6 @@ describe("Offline Editing", function()
expect(result).toBe(6);
done();
});
countFeatures(g_featureLayers[0], function(success,result)
{
expect(success).toBeTruthy();
expect(result.count).toBe(3); // still 3, the delete is still offline
done();
});
},
function(error)
{
@ -647,13 +641,13 @@ describe("Offline Editing", function()
g_offlineFeaturesManager.goOnline(function(results,responses) {
console.log("went online");
//expect(g_offlineFeaturesManager.getOnlineStatus()).toBe(g_offlineFeaturesManager.ONLINE);
//expect(listener).toHaveBeenCalled();
//expect(results.features.success).toBeTruthy();
expect(g_offlineFeaturesManager.getOnlineStatus()).toBe(g_offlineFeaturesManager.ONLINE);
expect(listener).toHaveBeenCalled();
expect(results.features.success).toBeTruthy();
console.log("RESPONSES " + JSON.stringify(responses) + ", " + JSON.stringify(results))
expect(Object.keys(results.features.responses).length).toBe(2);
expect(Object.keys(results.features.responses).length).toBe(9);
//for (var layerUrl in results.features.responses) {
// if (!results.features.responses.hasOwnProperty(layerUrl))
// continue;