summaryrefslogtreecommitdiff
path: root/includes/js/dojox/off/sync.js
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dojox/off/sync.js')
-rw-r--r--includes/js/dojox/off/sync.js690
1 files changed, 0 insertions, 690 deletions
diff --git a/includes/js/dojox/off/sync.js b/includes/js/dojox/off/sync.js
deleted file mode 100644
index 9927fbe..0000000
--- a/includes/js/dojox/off/sync.js
+++ /dev/null
@@ -1,690 +0,0 @@
-if(!dojo._hasResource["dojox.off.sync"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.off.sync"] = true;
-dojo.provide("dojox.off.sync");
-
-dojo.require("dojox.storage.GearsStorageProvider");
-dojo.require("dojox.off._common");
-dojo.require("dojox.off.files");
-
-// Author: Brad Neuberg, bkn3@columbia.edu, http://codinginparadise.org
-
-// summary:
-// Exposes syncing functionality to offline applications
-dojo.mixin(dojox.off.sync, {
- // isSyncing: boolean
- // Whether we are in the middle of a syncing session.
- isSyncing: false,
-
- // cancelled: boolean
- // Whether we were cancelled during our last sync request or not. If
- // we are cancelled, then successful will be false.
- cancelled: false,
-
- // successful: boolean
- // Whether the last sync was successful or not. If false, an error
- // occurred.
- successful: true,
-
- // details: String[]
- // Details on the sync. If the sync was successful, this will carry
- // any conflict or merging messages that might be available; if the
- // sync was unsuccessful, this will have an error message. For both
- // of these, this should be an array of Strings, where each string
- // carries details on the sync.
- // Example:
- // dojox.off.sync.details = ["The document 'foobar' had conflicts - yours one",
- // "The document 'hello world' was automatically merged"];
- details: [],
-
- // error: boolean
- // Whether an error occurred during the syncing process.
- error: false,
-
- // actions: dojox.off.sync.ActionLog
- // Our ActionLog that we store offline actions into for later
- // replaying when we go online
- actions: null,
-
- // autoSync: boolean
- // For advanced usage; most developers can ignore this.
- // Whether we do automatically sync on page load or when we go online.
- // If true we do, if false syncing must be manually initiated.
- // Defaults to true.
- autoSync: true,
-
- // summary:
- // An event handler that is called during the syncing process with
- // the state of syncing. It is important that you connect to this
- // method and respond to certain sync events, especially the
- // "download" event.
- // description:
- // This event handler is called during the syncing process. You can
- // do a dojo.connect to receive sync feedback:
- //
- // dojo.connect(dojox.off.sync, "onSync", someFunc);
- //
- // You will receive one argument, which is the type of the event
- // and which can have the following values.
- //
- // The most common two types that you need to care about are "download"
- // and "finished", especially if you are using the default
- // Dojo Offline UI widget that does the hard work of informing
- // the user through the UI about what is occuring during syncing.
- //
- // If you receive the "download" event, you should make a network call
- // to retrieve and store your data somehow for offline access. The
- // "finished" event indicates that syncing is done. An example:
- //
- // dojo.connect(dojox.off.sync, "onSync", function(type){
- // if(type == "download"){
- // // make a network call to download some data
- // // for use offline
- // dojo.xhrGet({
- // url: "downloadData.php",
- // handleAs: "javascript",
- // error: function(err){
- // dojox.off.sync.finishedDownloading(false, "Can't download data");
- // },
- // load: function(data){
- // // store our data
- // dojox.storage.put("myData", data);
- //
- // // indicate we are finished downloading
- // dojox.off.sync.finishedDownloading(true);
- // }
- // });
- // }else if(type == "finished"){
- // // update UI somehow to indicate we are finished,
- // // such as using the download data to change the
- // // available data
- // }
- // })
- //
- // Here is the full list of event types if you want to do deep
- // customization, such as updating your UI to display the progress
- // of syncing (note that the default Dojo Offline UI widget does
- // this for you if you choose to pull that in). Most of these
- // are only appropriate for advanced usage and can be safely
- // ignored:
- //
- // * "start"
- // syncing has started
- // * "refreshFiles"
- // syncing will begin refreshing
- // our offline file cache
- // * "upload"
- // syncing will begin uploading
- // any local data changes we have on the client.
- // This event is fired before we fire
- // the dojox.off.sync.actions.onReplay event for
- // each action to replay; use it to completely
- // over-ride the replaying behavior and prevent
- // it entirely, perhaps rolling your own sync
- // protocol if needed.
- // * "download"
- // syncing will begin downloading any new data that is
- // needed into persistent storage. Applications are required to
- // implement this themselves, storing the required data into
- // persistent local storage using Dojo Storage.
- // * "finished"
- // syncing is finished; this
- // will be called whether an error ocurred or not; check
- // dojox.off.sync.successful and dojox.off.sync.error for sync details
- // * "cancel"
- // Fired when canceling has been initiated; canceling will be
- // attempted, followed by the sync event "finished".
- onSync: function(/* String */ type){},
-
- synchronize: function(){ /* void */
- // summary: Starts synchronizing
-
- //dojo.debug("synchronize");
- if(this.isSyncing || dojox.off.goingOnline || (!dojox.off.isOnline)){
- return;
- }
-
- this.isSyncing = true;
- this.successful = false;
- this.details = [];
- this.cancelled = false;
-
- this.start();
- },
-
- cancel: function(){ /* void */
- // summary:
- // Attempts to cancel this sync session
-
- if(!this.isSyncing){ return; }
-
- this.cancelled = true;
- if(dojox.off.files.refreshing){
- dojox.off.files.abortRefresh();
- }
-
- this.onSync("cancel");
- },
-
- finishedDownloading: function(successful /* boolean? */,
- errorMessage /* String? */){
- // summary:
- // Applications call this method from their
- // after getting a "download" event in
- // dojox.off.sync.onSync to signal that
- // they are finished downloading any data
- // that should be available offline
- // successful: boolean?
- // Whether our downloading was successful or not.
- // If not present, defaults to true.
- // errorMessage: String?
- // If unsuccessful, a message explaining why
- if(typeof successful == "undefined"){
- successful = true;
- }
-
- if(!successful){
- this.successful = false;
- this.details.push(errorMessage);
- this.error = true;
- }
-
- this.finished();
- },
-
- start: function(){ /* void */
- // summary:
- // For advanced usage; most developers can ignore this.
- // Called at the start of the syncing process. Advanced
- // developers can over-ride this method to use their
- // own sync mechanism to start syncing.
-
- if(this.cancelled){
- this.finished();
- return;
- }
- this.onSync("start");
- this.refreshFiles();
- },
-
- refreshFiles: function(){ /* void */
- // summary:
- // For advanced usage; most developers can ignore this.
- // Called when we are going to refresh our list
- // of offline files during syncing. Advanced developers
- // can over-ride this method to do some advanced magic related to
- // refreshing files.
-
- //dojo.debug("refreshFiles");
- if(this.cancelled){
- this.finished();
- return;
- }
-
- this.onSync("refreshFiles");
-
- dojox.off.files.refresh(dojo.hitch(this, function(error, errorMessages){
- if(error){
- this.error = true;
- this.successful = false;
- for(var i = 0; i < errorMessages.length; i++){
- this.details.push(errorMessages[i]);
- }
-
- // even if we get an error while syncing files,
- // keep syncing so we can upload and download
- // data
- }
-
- this.upload();
- }));
- },
-
- upload: function(){ /* void */
- // summary:
- // For advanced usage; most developers can ignore this.
- // Called when syncing wants to upload data. Advanced
- // developers can over-ride this method to completely
- // throw away the Action Log and replaying system
- // and roll their own advanced sync mechanism if needed.
-
- if(this.cancelled){
- this.finished();
- return;
- }
-
- this.onSync("upload");
-
- // when we are done uploading start downloading
- dojo.connect(this.actions, "onReplayFinished", this, this.download);
-
- // replay the actions log
- this.actions.replay();
- },
-
- download: function(){ /* void */
- // summary:
- // For advanced usage; most developers can ignore this.
- // Called when syncing wants to download data. Advanced
- // developers can over-ride this method to use their
- // own sync mechanism.
-
- if(this.cancelled){
- this.finished();
- return;
- }
-
- // apps should respond to the "download"
- // event to download their data; when done
- // they must call dojox.off.sync.finishedDownloading()
- this.onSync("download");
- },
-
- finished: function(){ /* void */
- // summary:
- // For advanced usage; most developers can ignore this.
- // Called when syncing is finished. Advanced
- // developers can over-ride this method to clean
- // up after finishing their own sync
- // mechanism they might have rolled.
- this.isSyncing = false;
-
- this.successful = (!this.cancelled && !this.error);
-
- this.onSync("finished");
- },
-
- _save: function(callback){
- this.actions._save(function(){
- callback();
- });
- },
-
- _load: function(callback){
- this.actions._load(function(){
- callback();
- });
- }
-});
-
-
-// summary:
-// A class that records actions taken by a user when they are offline,
-// suitable for replaying when the network reappears.
-// description:
-// The basic idea behind this method is to record user actions that would
-// normally have to contact a server into an action log when we are
-// offline, so that later when we are online we can simply replay this log
-// in the order user actions happened so that they can be executed against
-// the server, causing synchronization to happen.
-//
-// When we replay, for each of the actions that were added, we call a
-// method named onReplay that applications should connect to and
-// which will be called over and over for each of our actions --
-// applications should take the offline action
-// information and use it to talk to a server to have this action
-// actually happen online, 'syncing' themselves with the server.
-//
-// For example, if the action was "update" with the item that was updated, we
-// might call some RESTian server API that exists for updating an item in
-// our application. The server could either then do sophisticated merging
-// and conflict resolution on the server side, for example, allowing you
-// to pop up a custom merge UI, or could do automatic merging or nothing
-// of the sort. When you are finished with this particular action, your
-// application is then required to call continueReplay() on the actionLog object
-// passed to onReplay() to continue replaying the action log, or haltReplay()
-// with the reason for halting to completely stop the syncing/replaying
-// process.
-//
-// For example, imagine that we have a web application that allows us to add
-// contacts. If we are offline, and we update a contact, we would add an action;
-// imagine that the user has to click an Update button after changing the values
-// for a given contact:
-//
-// dojox.off.whenOffline(dojo.byId("updateButton"), "onclick", function(evt){
-// // get the updated customer values
-// var customer = getCustomerValues();
-//
-// // we are offline -- just record this action
-// var action = {name: "update", customer: customer};
-// dojox.off.sync.actions.add(action)
-//
-// // persist this customer data into local storage as well
-// dojox.storage.put(customer.name, customer);
-// })
-//
-// Then, when we go back online, the dojox.off.sync.actions.onReplay event
-// will fire over and over, once for each action that was recorded while offline:
-//
-// dojo.connect(dojox.off.sync.actions, "onReplay", function(action, actionLog){
-// // called once for each action we added while offline, in the order
-// // they were added
-// if(action.name == "update"){
-// var customer = action.customer;
-//
-// // call some network service to update this customer
-// dojo.xhrPost({
-// url: "updateCustomer.php",
-// content: {customer: dojo.toJson(customer)},
-// error: function(err){
-// actionLog.haltReplay(err);
-// },
-// load: function(data){
-// actionLog.continueReplay();
-// }
-// })
-// }
-// })
-//
-// Note that the actions log is always automatically persisted locally while using it, so
-// that if the user closes the browser or it crashes the actions will safely be stored
-// for later replaying.
-dojo.declare("dojox.off.sync.ActionLog", null, {
- // entries: Array
- // An array of our action entries, where each one is simply a custom
- // object literal that were passed to add() when this action entry
- // was added.
- entries: [],
-
- // reasonHalted: String
- // If we halted, the reason why
- reasonHalted: null,
-
- // isReplaying: boolean
- // If true, we are in the middle of replaying a command log; if false,
- // then we are not
- isReplaying: false,
-
- // autoSave: boolean
- // Whether we automatically save the action log after each call to
- // add(); defaults to true. For applications that are rapidly adding
- // many action log entries in a short period of time, it can be
- // useful to set this to false and simply call save() yourself when
- // you are ready to persist your command log -- otherwise performance
- // could be slow as the default action is to attempt to persist the
- // actions log constantly with calls to add().
- autoSave: true,
-
- add: function(action /* Object */){ /* void */
- // summary:
- // Adds an action to our action log
- // description:
- // This method will add an action to our
- // action log, later to be replayed when we
- // go from offline to online. 'action'
- // will be available when this action is
- // replayed and will be passed to onReplay.
- //
- // Example usage:
- //
- // dojox.off.sync.log.add({actionName: "create", itemType: "document",
- // {title: "Message", content: "Hello World"}});
- //
- // The object literal is simply a custom object appropriate
- // for our application -- it can be anything that preserves the state
- // of a user action that will be executed when we go back online
- // and replay this log. In the above example,
- // "create" is the name of this action; "documents" is the
- // type of item this command is operating on, such as documents, contacts,
- // tasks, etc.; and the final argument is the document that was created.
-
- if(this.isReplaying){
- throw "Programming error: you can not call "
- + "dojox.off.sync.actions.add() while "
- + "we are replaying an action log";
- }
-
- this.entries.push(action);
-
- // save our updated state into persistent
- // storage
- if(this.autoSave){
- this._save();
- }
- },
-
- onReplay: function(action /* Object */,
- actionLog /* dojox.off.sync.ActionLog */){ /* void */
- // summary:
- // Called when we replay our log, for each of our action
- // entries.
- // action: Object
- // A custom object literal representing an action for this
- // application, such as
- // {actionName: "create", item: {title: "message", content: "hello world"}}
- // actionLog: dojox.off.sync.ActionLog
- // A reference to the dojox.off.sync.actions log so that developers
- // can easily call actionLog.continueReplay() or actionLog.haltReplay().
- // description:
- // This callback should be connected to by applications so that
- // they can sync themselves when we go back online:
- //
- // dojo.connect(dojox.off.sync.actions, "onReplay", function(action, actionLog){
- // // do something
- // })
- //
- // When we replay our action log, this callback is called for each
- // of our action entries in the order they were added. The
- // 'action' entry that was passed to add() for this action will
- // also be passed in to onReplay, so that applications can use this information
- // to do their syncing, such as contacting a server web-service
- // to create a new item, for example.
- //
- // Inside the method you connected to onReplay, you should either call
- // actionLog.haltReplay(reason) if an error occurred and you would like to halt
- // action replaying or actionLog.continueReplay() to have the action log
- // continue replaying its log and proceed to the next action;
- // the reason you must call these is the action you execute inside of
- // onAction will probably be asynchronous, since it will be talking on
- // the network, and you should call one of these two methods based on
- // the result of your network call.
- },
-
- length: function(){ /* Number */
- // summary:
- // Returns the length of this
- // action log
- return this.entries.length;
- },
-
- haltReplay: function(reason /* String */){ /* void */
- // summary: Halts replaying this command log.
- // reason: String
- // The reason we halted.
- // description:
- // This method is called as we are replaying an action log; it
- // can be called from dojox.off.sync.actions.onReplay, for
- // example, for an application to indicate an error occurred
- // while replaying this action, halting further processing of
- // the action log. Note that any action log entries that
- // were processed before have their effects retained (i.e.
- // they are not rolled back), while the action entry that was
- // halted stays in our list of actions to later be replayed.
- if(!this.isReplaying){
- return;
- }
-
- if(reason){
- this.reasonHalted = reason.toString();
- }
-
- // save the state of our action log, then
- // tell anyone who is interested that we are
- // done when we are finished saving
- if(this.autoSave){
- var self = this;
- this._save(function(){
- self.isReplaying = false;
- self.onReplayFinished();
- });
- }else{
- this.isReplaying = false;
- this.onReplayFinished();
- }
- },
-
- continueReplay: function(){ /* void */
- // summary:
- // Indicates that we should continue processing out list of
- // actions.
- // description:
- // This method is called by applications that have overridden
- // dojox.off.sync.actions.onReplay() to continue replaying our
- // action log after the application has finished handling the
- // current action.
- if(!this.isReplaying){
- return;
- }
-
- // shift off the old action we just ran
- this.entries.shift();
-
- // are we done?
- if(!this.entries.length){
- // save the state of our action log, then
- // tell anyone who is interested that we are
- // done when we are finished saving
- if(this.autoSave){
- var self = this;
- this._save(function(){
- self.isReplaying = false;
- self.onReplayFinished();
- });
- return;
- }else{
- this.isReplaying = false;
- this.onReplayFinished();
- return;
- }
- }
-
- // get the next action
- var nextAction = this.entries[0];
- this.onReplay(nextAction, this);
- },
-
- clear: function(){ /* void */
- // summary:
- // Completely clears this action log of its entries
-
- if(this.isReplaying){
- return;
- }
-
- this.entries = [];
-
- // save our updated state into persistent
- // storage
- if(this.autoSave){
- this._save();
- }
- },
-
- replay: function(){ /* void */
- // summary:
- // For advanced usage; most developers can ignore this.
- // Replays all of the commands that have been
- // cached in this command log when we go back online;
- // onCommand will be called for each command we have
-
- if(this.isReplaying){
- return;
- }
-
- this.reasonHalted = null;
-
- if(!this.entries.length){
- this.onReplayFinished();
- return;
- }
-
- this.isReplaying = true;
-
- var nextAction = this.entries[0];
- this.onReplay(nextAction, this);
- },
-
- // onReplayFinished: Function
- // For advanced usage; most developers can ignore this.
- // Called when we are finished replaying our commands;
- // called if we have successfully exhausted all of our
- // commands, or if an error occurred during replaying.
- // The default implementation simply continues the
- // synchronization process. Connect to this to register
- // for the event:
- //
- // dojo.connect(dojox.off.sync.actions, "onReplayFinished",
- // someFunc)
- onReplayFinished: function(){
- },
-
- toString: function(){
- var results = "";
- results += "[";
-
- for(var i = 0; i < this.entries.length; i++){
- results += "{";
- for(var j in this.entries[i]){
- results += j + ": \"" + this.entries[i][j] + "\"";
- results += ", ";
- }
- results += "}, ";
- }
-
- results += "]";
-
- return results;
- },
-
- _save: function(callback){
- if(!callback){
- callback = function(){};
- }
-
- try{
- var self = this;
- var resultsHandler = function(status, key, message){
- //console.debug("resultsHandler, status="+status+", key="+key+", message="+message);
- if(status == dojox.storage.FAILED){
- dojox.off.onFrameworkEvent("save",
- {status: dojox.storage.FAILED,
- isCoreSave: true,
- key: key,
- value: message,
- namespace: dojox.off.STORAGE_NAMESPACE});
- callback();
- }else if(status == dojox.storage.SUCCESS){
- callback();
- }
- };
-
- dojox.storage.put("actionlog", this.entries, resultsHandler,
- dojox.off.STORAGE_NAMESPACE);
- }catch(exp){
- console.debug("dojox.off.sync._save: " + exp.message||exp);
- dojox.off.onFrameworkEvent("save",
- {status: dojox.storage.FAILED,
- isCoreSave: true,
- key: "actionlog",
- value: this.entries,
- namespace: dojox.off.STORAGE_NAMESPACE});
- callback();
- }
- },
-
- _load: function(callback){
- var entries = dojox.storage.get("actionlog", dojox.off.STORAGE_NAMESPACE);
-
- if(!entries){
- entries = [];
- }
-
- this.entries = entries;
-
- callback();
- }
- }
-);
-
-dojox.off.sync.actions = new dojox.off.sync.ActionLog();
-
-}