From 1c5685d68f1b73270fb814fe04cbb490eb90ba5f Mon Sep 17 00:00:00 2001 From: mensonge Date: Fri, 14 Nov 2008 15:39:19 +0000 Subject: Minor fix: Remove DOJO library (60Mo) replaced by link to Google CDN (online DOJO library) git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@159 b3834d28-1941-0410-a4f8-b48e95affb8f --- includes/js/dojox/off/README | 28 - includes/js/dojox/off/_common.js | 559 -- includes/js/dojox/off/docs/bookmarklets.html | 10 - includes/js/dojox/off/files.js | 454 -- includes/js/dojox/off/network_check.txt | 1 - includes/js/dojox/off/offline.js | 20 - includes/js/dojox/off/offline.js.uncompressed.js | 5910 -------------------- includes/js/dojox/off/resources/checkmark.png | Bin 27329 -> 0 bytes includes/js/dojox/off/resources/greenball.png | Bin 27414 -> 0 bytes includes/js/dojox/off/resources/learnhow.html | 43 - includes/js/dojox/off/resources/learnhow.js | 43 - includes/js/dojox/off/resources/offline-widget.css | 88 - .../off/resources/offline-widget.css.commented.css | 112 - .../js/dojox/off/resources/offline-widget.html | 40 - includes/js/dojox/off/resources/redball.png | Bin 27409 -> 0 bytes includes/js/dojox/off/resources/roller.gif | Bin 7462 -> 0 bytes includes/js/dojox/off/sync.js | 690 --- includes/js/dojox/off/ui.js | 622 -- 18 files changed, 8620 deletions(-) delete mode 100644 includes/js/dojox/off/README delete mode 100644 includes/js/dojox/off/_common.js delete mode 100644 includes/js/dojox/off/docs/bookmarklets.html delete mode 100644 includes/js/dojox/off/files.js delete mode 100644 includes/js/dojox/off/network_check.txt delete mode 100644 includes/js/dojox/off/offline.js delete mode 100644 includes/js/dojox/off/offline.js.uncompressed.js delete mode 100644 includes/js/dojox/off/resources/checkmark.png delete mode 100644 includes/js/dojox/off/resources/greenball.png delete mode 100644 includes/js/dojox/off/resources/learnhow.html delete mode 100644 includes/js/dojox/off/resources/learnhow.js delete mode 100644 includes/js/dojox/off/resources/offline-widget.css delete mode 100644 includes/js/dojox/off/resources/offline-widget.css.commented.css delete mode 100644 includes/js/dojox/off/resources/offline-widget.html delete mode 100644 includes/js/dojox/off/resources/redball.png delete mode 100644 includes/js/dojox/off/resources/roller.gif delete mode 100644 includes/js/dojox/off/sync.js delete mode 100644 includes/js/dojox/off/ui.js (limited to 'includes/js/dojox/off') diff --git a/includes/js/dojox/off/README b/includes/js/dojox/off/README deleted file mode 100644 index 64a1f4b..0000000 --- a/includes/js/dojox/off/README +++ /dev/null @@ -1,28 +0,0 @@ -------------------------------------------------------------------------------- -Dojo Offline -------------------------------------------------------------------------------- -Release date: May 2007 (Release date used as version) -------------------------------------------------------------------------------- -Project state: -experimental -------------------------------------------------------------------------------- -Credits - Brad Neuberg - SitePen -------------------------------------------------------------------------------- -Project description -Toolkit to help build offline web applications; uses Google Gears under the covers. -------------------------------------------------------------------------------- -Dependencies: -Dojo Storage, Dojo Crypto, Dojo Core, Google Gears -------------------------------------------------------------------------------- -Documentation - -See http://docs.google.com/View?docid=dhkhksk4_8gdp9gr for documentation and a t -utorial on using Dojo Offline. - -------------------------------------------------------------------------------- -Installation instructions - -See full documentation at URL given right above. -------------------------------------------------------------------------------- diff --git a/includes/js/dojox/off/_common.js b/includes/js/dojox/off/_common.js deleted file mode 100644 index 005cd31..0000000 --- a/includes/js/dojox/off/_common.js +++ /dev/null @@ -1,559 +0,0 @@ -if(!dojo._hasResource["dojox.off._common"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojox.off._common"] = true; -dojo.provide("dojox.off._common"); - -dojo.require("dojox.storage"); -dojo.require("dojox.sql"); -dojo.require("dojox.off.sync"); - -// Author: Brad Neuberg, bkn3@columbia.edu, http://codinginparadise.org - -// summary: -// dojox.off is the main object for offline applications. -dojo.mixin(dojox.off, { - // isOnline: boolean - // true if we are online, false if not - isOnline: false, - - // NET_CHECK: int - // For advanced usage; most developers can ignore this. - // Time in seconds on how often we should check the status of the - // network with an automatic background timer. The current default - // is 5 seconds. - NET_CHECK: 5, - - // STORAGE_NAMESPACE: String - // For advanced usage; most developers can ignore this. - // The namespace we use to save core data into Dojo Storage. - STORAGE_NAMESPACE: "_dot", - - // enabled: boolean - // For advanced usage; most developers can ignore this. - // Whether offline ability is enabled or not. Defaults to true. - enabled: true, - - // availabilityURL: String - // For advanced usage; most developers can ignore this. - // The URL to check for site availability. We do a GET request on - // this URL to check for site availability. By default we check for a - // simple text file in src/off/network_check.txt that has one value - // it, the value '1'. - availabilityURL: dojo.moduleUrl("dojox", "off/network_check.txt"), - - // goingOnline: boolean - // For advanced usage; most developers can ignore this. - // True if we are attempting to go online, false otherwise - goingOnline: false, - - // coreOpFailed: boolean - // For advanced usage; most developers can ignore this. - // A flag set by the Dojo Offline framework that indicates that the - // user denied some operation that required the offline cache or an - // operation failed in some critical way that was unrecoverable. For - // example, if the offline cache is Google Gears and we try to get a - // Gears database, a popup window appears asking the user whether they - // will approve or deny this request. If the user denies the request, - // and we are doing some operation that is core to Dojo Offline, then - // we set this flag to 'true'. This flag causes a 'fail fast' - // condition, turning off offline ability. - coreOpFailed: false, - - // doNetChecking: boolean - // For advanced usage; most developers can ignore this. - // Whether to have a timing interval in the background doing automatic - // network checks at regular intervals; the length of time between - // checks is controlled by dojox.off.NET_CHECK. Defaults to true. - doNetChecking: true, - - // hasOfflineCache: boolean - // For advanced usage; most developers can ignore this. - // Determines if an offline cache is available or installed; an - // offline cache is a facility that can truely cache offline - // resources, such as JavaScript, HTML, etc. in such a way that they - // won't be removed from the cache inappropriately like a browser - // cache would. If this is false then an offline cache will be - // installed. Only Google Gears is currently supported as an offline - // cache. Future possible offline caches include Firefox 3. - hasOfflineCache: null, - - // browserRestart: boolean - // For advanced usage; most developers can ignore this. - // If true, the browser must be restarted to register the existence of - // a new host added offline (from a call to addHostOffline); if false, - // then nothing is needed. - browserRestart: false, - - _STORAGE_APP_NAME: window.location.href.replace(/[^0-9A-Za-z_]/g, "_"), - - _initializeCalled: false, - _storageLoaded: false, - _pageLoaded: false, - - onLoad: function(){ - // summary: - // Called when Dojo Offline can be used. - // description: - // Do a dojo.connect to this to know when you can - // start using Dojo Offline: - // dojo.connect(dojox.off, "onLoad", myFunc); - }, - - onNetwork: function(type){ - // summary: - // Called when our on- or offline- status changes. - // description: - // If we move online, then this method is called with the - // value "online". If we move offline, then this method is - // called with the value "offline". You can connect to this - // method to do add your own behavior: - // - // dojo.connect(dojox.off, "onNetwork", someFunc) - // - // Note that if you are using the default Dojo Offline UI - // widget that most of the on- and off-line notification - // and syncing is automatically handled and provided to the - // user. - // type: String - // Either "online" or "offline". - }, - - initialize: function(){ /* void */ - // summary: - // Called when a Dojo Offline-enabled application is finished - // configuring Dojo Offline, and is ready for Dojo Offline to - // initialize itself. - // description: - // When an application has finished filling out the variables Dojo - // Offline needs to work, such as dojox.off.ui.appName, it must - // this method to tell Dojo Offline to initialize itself. - - // Note: - // This method is needed for a rare edge case. In some conditions, - // especially if we are dealing with a compressed Dojo build, the - // entire Dojo Offline subsystem might initialize itself and be - // running even before the JavaScript for an application has had a - // chance to run and configure Dojo Offline, causing Dojo Offline - // to have incorrect initialization parameters for a given app, - // such as no value for dojox.off.ui.appName. This method is - // provided to prevent this scenario, to slightly 'slow down' Dojo - // Offline so it can be configured before running off and doing - // its thing. - - //console.debug("dojox.off.initialize"); - this._initializeCalled = true; - - if(this._storageLoaded && this._pageLoaded){ - this._onLoad(); - } - }, - - goOffline: function(){ /* void */ - // summary: - // For advanced usage; most developers can ignore this. - // Manually goes offline, away from the network. - if((dojox.off.sync.isSyncing)||(this.goingOnline)){ return; } - - this.goingOnline = false; - this.isOnline = false; - }, - - goOnline: function(callback){ /* void */ - // summary: - // For advanced usage; most developers can ignore this. - // Attempts to go online. - // description: - // Attempts to go online, making sure this web application's web - // site is available. 'callback' is called asychronously with the - // result of whether we were able to go online or not. - // callback: Function - // An optional callback function that will receive one argument: - // whether the site is available or not and is boolean. If this - // function is not present we call dojo.xoff.onOnline instead if - // we are able to go online. - - //console.debug("goOnline"); - - if(dojox.off.sync.isSyncing || dojox.off.goingOnline){ - return; - } - - this.goingOnline = true; - this.isOnline = false; - - // see if can reach our web application's web site - this._isSiteAvailable(callback); - }, - - onFrameworkEvent: function(type /* String */, saveData /* Object? */){ - // summary: - // For advanced usage; most developers can ignore this. - // A standard event handler that can be attached to to find out - // about low-level framework events. Most developers will not need to - // attach to this method; it is meant for low-level information - // that can be useful for updating offline user-interfaces in - // exceptional circumstances. The default Dojo Offline UI - // widget takes care of most of these situations. - // type: String - // The type of the event: - // - // * "offlineCacheInstalled" - // An event that is fired when a user - // has installed an offline cache after the page has been loaded. - // If a user didn't have an offline cache when the page loaded, a - // UI of some kind might have prompted them to download one. This - // method is called if they have downloaded and installed an - // offline cache so a UI can reinitialize itself to begin using - // this offline cache. - // * "coreOperationFailed" - // Fired when a core operation during interaction with the - // offline cache is denied by the user. Some offline caches, such - // as Google Gears, prompts the user to approve or deny caching - // files, using the database, and more. If the user denies a - // request that is core to Dojo Offline's operation, we set - // dojox.off.coreOpFailed to true and call this method for - // listeners that would like to respond some how to Dojo Offline - // 'failing fast'. - // * "save" - // Called whenever the framework saves data into persistent - // storage. This could be useful for providing save feedback - // or providing appropriate error feedback if saving fails - // due to a user not allowing the save to occur - // saveData: Object? - // If the type was 'save', then a saveData object is provided with - // further save information. This object has the following properties: - // - // * status - dojox.storage.SUCCESS, dojox.storage.PENDING, dojox.storage.FAILED - // Whether the save succeeded, whether it is pending based on a UI - // dialog asking the user for permission, or whether it failed. - // - // * isCoreSave - boolean - // If true, then this save was for a core piece of data necessary - // for the functioning of Dojo Offline. If false, then it is a - // piece of normal data being saved for offline access. Dojo - // Offline will 'fail fast' if some core piece of data could not - // be saved, automatically setting dojox.off.coreOpFailed to - // 'true' and dojox.off.enabled to 'false'. - // - // * key - String - // The key that we are attempting to persist - // - // * value - Object - // The object we are trying to persist - // - // * namespace - String - // The Dojo Storage namespace we are saving this key/value pair - // into, such as "default", "Documents", "Contacts", etc. - // Optional. - if(type == "save"){ - if(saveData.isCoreSave && (saveData.status == dojox.storage.FAILED)){ - dojox.off.coreOpFailed = true; - dojox.off.enabled = false; - - // FIXME: Stop the background network thread - dojox.off.onFrameworkEvent("coreOperationFailed"); - } - }else if(type == "coreOperationFailed"){ - dojox.off.coreOpFailed = true; - dojox.off.enabled = false; - // FIXME: Stop the background network thread - } - }, - - _checkOfflineCacheAvailable: function(callback){ - // is a true, offline cache running on this machine? - this.hasOfflineCache = dojo.isGears; - - callback(); - }, - - _onLoad: function(){ - //console.debug("dojox.off._onLoad"); - - // both local storage and the page are finished loading - - // cache the Dojo JavaScript -- just use the default dojo.js - // name for the most common scenario - // FIXME: TEST: Make sure syncing doesn't break if dojo.js - // can't be found, or report an error to developer - dojox.off.files.cache(dojo.moduleUrl("dojo", "dojo.js")); - - // pull in the files needed by Dojo - this._cacheDojoResources(); - - // FIXME: need to pull in the firebug lite files here! - // workaround or else we will get an error on page load - // from Dojo that it can't find 'console.debug' for optimized builds - // dojox.off.files.cache(dojo.config.baseRelativePath + "src/debug.js"); - - // make sure that resources needed by all of our underlying - // Dojo Storage storage providers will be available - // offline - dojox.off.files.cache(dojox.storage.manager.getResourceList()); - - // slurp the page if the end-developer wants that - dojox.off.files._slurp(); - - // see if we have an offline cache; when done, move - // on to the rest of our startup tasks - this._checkOfflineCacheAvailable(dojo.hitch(this, "_onOfflineCacheChecked")); - }, - - _onOfflineCacheChecked: function(){ - // this method is part of our _onLoad series of startup tasks - - // if we have an offline cache, see if we have been added to the - // list of available offline web apps yet - if(this.hasOfflineCache && this.enabled){ - // load framework data; when we are finished, continue - // initializing ourselves - this._load(dojo.hitch(this, "_finishStartingUp")); - }else if(this.hasOfflineCache && !this.enabled){ - // we have an offline cache, but it is disabled for some reason - // perhaps due to the user denying a core operation - this._finishStartingUp(); - }else{ - this._keepCheckingUntilInstalled(); - } - }, - - _keepCheckingUntilInstalled: function(){ - // this method is part of our _onLoad series of startup tasks - - // kick off a background interval that keeps - // checking to see if an offline cache has been - // installed since this page loaded - - // FIXME: Gears: See if we are installed somehow after the - // page has been loaded - - // now continue starting up - this._finishStartingUp(); - }, - - _finishStartingUp: function(){ - //console.debug("dojox.off._finishStartingUp"); - - // this method is part of our _onLoad series of startup tasks - - if(!this.hasOfflineCache){ - this.onLoad(); - }else if(this.enabled){ - // kick off a thread to check network status on - // a regular basis - this._startNetworkThread(); - - // try to go online - this.goOnline(dojo.hitch(this, function(){ - //console.debug("Finished trying to go online"); - // indicate we are ready to be used - dojox.off.onLoad(); - })); - }else{ // we are disabled or a core operation failed - if(this.coreOpFailed){ - this.onFrameworkEvent("coreOperationFailed"); - }else{ - this.onLoad(); - } - } - }, - - _onPageLoad: function(){ - //console.debug("dojox.off._onPageLoad"); - this._pageLoaded = true; - - if(this._storageLoaded && this._initializeCalled){ - this._onLoad(); - } - }, - - _onStorageLoad: function(){ - //console.debug("dojox.off._onStorageLoad"); - this._storageLoaded = true; - - // were we able to initialize storage? if - // not, then this is a core operation, and - // let's indicate we will need to fail fast - if(!dojox.storage.manager.isAvailable() - && dojox.storage.manager.isInitialized()){ - this.coreOpFailed = true; - this.enabled = false; - } - - if(this._pageLoaded && this._initializeCalled){ - this._onLoad(); - } - }, - - _isSiteAvailable: function(callback){ - // summary: - // Determines if our web application's website is available. - // description: - // This method will asychronously determine if our web - // application's web site is available, which is a good proxy for - // network availability. The URL dojox.off.availabilityURL is - // used, which defaults to this site's domain name (ex: - // foobar.com). We check for dojox.off.AVAILABILITY_TIMEOUT (in - // seconds) and abort after that - // callback: Function - // An optional callback function that will receive one argument: - // whether the site is available or not and is boolean. If this - // function is not present we call dojox.off.onNetwork instead if we - // are able to go online. - dojo.xhrGet({ - url: this._getAvailabilityURL(), - handleAs: "text", - timeout: this.NET_CHECK * 1000, - error: dojo.hitch(this, function(err){ - //console.debug("dojox.off._isSiteAvailable.error: " + err); - this.goingOnline = false; - this.isOnline = false; - if(callback){ callback(false); } - }), - load: dojo.hitch(this, function(data){ - //console.debug("dojox.off._isSiteAvailable.load, data="+data); - this.goingOnline = false; - this.isOnline = true; - - if(callback){ callback(true); - }else{ this.onNetwork("online"); } - }) - }); - }, - - _startNetworkThread: function(){ - //console.debug("startNetworkThread"); - - // kick off a thread that does periodic - // checks on the status of the network - if(!this.doNetChecking){ - return; - } - - window.setInterval(dojo.hitch(this, function(){ - var d = dojo.xhrGet({ - url: this._getAvailabilityURL(), - handleAs: "text", - timeout: this.NET_CHECK * 1000, - error: dojo.hitch(this, - function(err){ - if(this.isOnline){ - this.isOnline = false; - - // FIXME: xhrGet() is not - // correctly calling abort - // on the XHR object when - // it times out; fix inside - // there instead of externally - // here - try{ - if(typeof d.ioArgs.xhr.abort == "function"){ - d.ioArgs.xhr.abort(); - } - }catch(e){} - - // if things fell in the middle of syncing, - // stop syncing - dojox.off.sync.isSyncing = false; - - this.onNetwork("offline"); - } - } - ), - load: dojo.hitch(this, - function(data){ - if(!this.isOnline){ - this.isOnline = true; - this.onNetwork("online"); - } - } - ) - }); - - }), this.NET_CHECK * 1000); - }, - - _getAvailabilityURL: function(){ - var url = this.availabilityURL.toString(); - - // bust the browser's cache to make sure we are really talking to - // the server - if(url.indexOf("?") == -1){ - url += "?"; - }else{ - url += "&"; - } - url += "browserbust=" + new Date().getTime(); - - return url; - }, - - _onOfflineCacheInstalled: function(){ - this.onFrameworkEvent("offlineCacheInstalled"); - }, - - _cacheDojoResources: function(){ - // if we are a non-optimized build, then the core Dojo bootstrap - // system was loaded as separate JavaScript files; - // add these to our offline cache list. these are - // loaded before the dojo.require() system exists - - // FIXME: create a better mechanism in the Dojo core to - // expose whether you are dealing with an optimized build; - // right now we just scan the SCRIPT tags attached to this - // page and see if there is one for _base/_loader/bootstrap.js - var isOptimizedBuild = true; - dojo.forEach(dojo.query("script"), function(i){ - var src = i.getAttribute("src"); - if(!src){ return; } - - if(src.indexOf("_base/_loader/bootstrap.js") != -1){ - isOptimizedBuild = false; - } - }); - - if(!isOptimizedBuild){ - dojox.off.files.cache(dojo.moduleUrl("dojo", "_base.js").uri); - dojox.off.files.cache(dojo.moduleUrl("dojo", "_base/_loader/loader.js").uri); - dojox.off.files.cache(dojo.moduleUrl("dojo", "_base/_loader/bootstrap.js").uri); - - // FIXME: pull in the host environment file in a more generic way - // for other host environments - dojox.off.files.cache(dojo.moduleUrl("dojo", "_base/_loader/hostenv_browser.js").uri); - } - - // add anything that was brought in with a - // dojo.require() that resulted in a JavaScript - // URL being fetched - - // FIXME: modify dojo/_base/_loader/loader.js to - // expose a public API to get this information - - for(var i = 0; i < dojo._loadedUrls.length; i++){ - dojox.off.files.cache(dojo._loadedUrls[i]); - } - - // FIXME: add the standard Dojo CSS file - }, - - _save: function(){ - // summary: - // Causes the Dojo Offline framework to save its configuration - // data into local storage. - }, - - _load: function(callback){ - // summary: - // Causes the Dojo Offline framework to load its configuration - // data from local storage - dojox.off.sync._load(callback); - } -}); - - -// wait until the storage system is finished loading -dojox.storage.manager.addOnLoad(dojo.hitch(dojox.off, "_onStorageLoad")); - -// wait until the page is finished loading -dojo.addOnLoad(dojox.off, "_onPageLoad"); - -} diff --git a/includes/js/dojox/off/docs/bookmarklets.html b/includes/js/dojox/off/docs/bookmarklets.html deleted file mode 100644 index c5ece2e..0000000 --- a/includes/js/dojox/off/docs/bookmarklets.html +++ /dev/null @@ -1,10 +0,0 @@ - - -

Browser Bookmarklets

- -

Drag the following bookmarklets to your links toolbar and press to clear the Google Gears cache:

- -

Firefox: Clear Gears Cache

-

Internet Explorer: Clear Gears Cache

- - diff --git a/includes/js/dojox/off/files.js b/includes/js/dojox/off/files.js deleted file mode 100644 index 6c19ea0..0000000 --- a/includes/js/dojox/off/files.js +++ /dev/null @@ -1,454 +0,0 @@ -if(!dojo._hasResource["dojox.off.files"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojox.off.files"] = true; -dojo.provide("dojox.off.files"); - -// Author: Brad Neuberg, bkn3@columbia.edu, http://codinginparadise.org - -// summary: -// Helps maintain resources that should be -// available offline, such as CSS files. -// description: -// dojox.off.files makes it easy to indicate -// what resources should be available offline, -// such as CSS files, JavaScript, HTML, etc. -dojox.off.files = { - // versionURL: String - // An optional file, that if present, records the version - // of our bundle of files to make available offline. If this - // file is present, and we are not currently debugging, - // then we only refresh our offline files if the version has - // changed. - versionURL: "version.js", - - // listOfURLs: Array - // For advanced usage; most developers can ignore this. - // Our list of URLs that will be cached and made available - // offline. - listOfURLs: [], - - // refreshing: boolean - // For advanced usage; most developers can ignore this. - // Whether we are currently in the middle - // of refreshing our list of offline files. - refreshing: false, - - _cancelID: null, - - _error: false, - _errorMessages: [], - _currentFileIndex: 0, - _store: null, - _doSlurp: false, - - slurp: function(){ - // summary: - // Autoscans the page to find all resources to - // cache. This includes scripts, images, CSS, and hyperlinks - // to pages that are in the same scheme/port/host as this - // page. We also scan the embedded CSS of any stylesheets - // to find @import statements and url()'s. - // You should call this method from the top-level, outside of - // any functions and before the page loads: - // - // - // - // Note that inline styles on elements are not handled (i.e. - // if you somehow have an inline style that uses a URL); - // object and embed tags are not scanned since their format - // differs based on type; and elements created by JavaScript - // after page load are not found. For these you must manually - // add them with a dojox.off.files.cache() method call. - - // just schedule the slurp once the page is loaded and - // Dojo Offline is ready to slurp; dojox.off will call - // our _slurp() method before indicating it is finished - // loading - this._doSlurp = true; - }, - - cache: function(urlOrList){ /* void */ - // summary: - // Caches a file or list of files to be available offline. This - // can either be a full URL, such as http://foobar.com/index.html, - // or a relative URL, such as ../index.html. This URL is not - // actually cached until dojox.off.sync.synchronize() is called. - // urlOrList: String or Array[] - // A URL of a file to cache or an Array of Strings of files to - // cache - - //console.debug("dojox.off.files.cache, urlOrList="+urlOrList); - - if(dojo.isString(urlOrList)){ - var url = this._trimAnchor(urlOrList+""); - if(!this.isAvailable(url)){ - this.listOfURLs.push(url); - } - }else if(urlOrList instanceof dojo._Url){ - var url = this._trimAnchor(urlOrList.uri); - if(!this.isAvailable(url)){ - this.listOfURLs.push(url); - } - }else{ - dojo.forEach(urlOrList, function(url){ - url = this._trimAnchor(url); - if(!this.isAvailable(url)){ - this.listOfURLs.push(url); - } - }, this); - } - }, - - printURLs: function(){ - // summary: - // A helper function that will dump and print out - // all of the URLs that are cached for offline - // availability. This can help with debugging if you - // are trying to make sure that all of your URLs are - // available offline - console.debug("The following URLs are cached for offline use:"); - dojo.forEach(this.listOfURLs, function(i){ - console.debug(i); - }); - }, - - remove: function(url){ /* void */ - // summary: - // Removes a URL from the list of files to cache. - // description: - // Removes a URL from the list of URLs to cache. Note that this - // does not actually remove the file from the offline cache; - // instead, it just prevents us from refreshing this file at a - // later time, so that it will naturally time out and be removed - // from the offline cache - // url: String - // The URL to remove - for(var i = 0; i < this.listOfURLs.length; i++){ - if(this.listOfURLs[i] == url){ - this.listOfURLs = this.listOfURLs.splice(i, 1); - break; - } - } - }, - - isAvailable: function(url){ /* boolean */ - // summary: - // Determines whether the given resource is available offline. - // url: String - // The URL to check - for(var i = 0; i < this.listOfURLs.length; i++){ - if(this.listOfURLs[i] == url){ - return true; - } - } - - return false; - }, - - refresh: function(callback){ /* void */ - //console.debug("dojox.off.files.refresh"); - // summary: - // For advanced usage; most developers can ignore this. - // Refreshes our list of offline resources, - // making them available offline. - // callback: Function - // A callback that receives two arguments: whether an error - // occurred, which is a boolean; and an array of error message strings - // with details on errors encountered. If no error occured then message is - // empty array with length 0. - try{ - if(dojo.config.isDebug){ - this.printURLs(); - } - - this.refreshing = true; - - if(this.versionURL){ - this._getVersionInfo(function(oldVersion, newVersion, justDebugged){ - //console.warn("getVersionInfo, oldVersion="+oldVersion+", newVersion="+newVersion - // + ", justDebugged="+justDebugged+", isDebug="+dojo.config.isDebug); - if(dojo.config.isDebug || !newVersion || justDebugged - || !oldVersion || oldVersion != newVersion){ - console.warn("Refreshing offline file list"); - this._doRefresh(callback, newVersion); - }else{ - console.warn("No need to refresh offline file list"); - callback(false, []); - } - }); - }else{ - console.warn("Refreshing offline file list"); - this._doRefresh(callback); - } - }catch(e){ - this.refreshing = false; - - // can't refresh files -- core operation -- - // fail fast - dojox.off.coreOpFailed = true; - dojox.off.enabled = false; - dojox.off.onFrameworkEvent("coreOperationFailed"); - } - }, - - abortRefresh: function(){ - // summary: - // For advanced usage; most developers can ignore this. - // Aborts and cancels a refresh. - if(!this.refreshing){ - return; - } - - this._store.abortCapture(this._cancelID); - this.refreshing = false; - }, - - _slurp: function(){ - if(!this._doSlurp){ - return; - } - - var handleUrl = dojo.hitch(this, function(url){ - if(this._sameLocation(url)){ - this.cache(url); - } - }); - - handleUrl(window.location.href); - - dojo.query("script").forEach(function(i){ - try{ - handleUrl(i.getAttribute("src")); - }catch(exp){ - //console.debug("dojox.off.files.slurp 'script' error: " - // + exp.message||exp); - } - }); - - dojo.query("link").forEach(function(i){ - try{ - if(!i.getAttribute("rel") - || i.getAttribute("rel").toLowerCase() != "stylesheet"){ - return; - } - - handleUrl(i.getAttribute("href")); - }catch(exp){ - //console.debug("dojox.off.files.slurp 'link' error: " - // + exp.message||exp); - } - }); - - dojo.query("img").forEach(function(i){ - try{ - handleUrl(i.getAttribute("src")); - }catch(exp){ - //console.debug("dojox.off.files.slurp 'img' error: " - // + exp.message||exp); - } - }); - - dojo.query("a").forEach(function(i){ - try{ - handleUrl(i.getAttribute("href")); - }catch(exp){ - //console.debug("dojox.off.files.slurp 'a' error: " - // + exp.message||exp); - } - }); - - // FIXME: handle 'object' and 'embed' tag - - // parse our style sheets for inline URLs and imports - dojo.forEach(document.styleSheets, function(sheet){ - try{ - if(sheet.cssRules){ // Firefox - dojo.forEach(sheet.cssRules, function(rule){ - var text = rule.cssText; - if(text){ - var matches = text.match(/url\(\s*([^\) ]*)\s*\)/i); - if(!matches){ - return; - } - - for(var i = 1; i < matches.length; i++){ - handleUrl(matches[i]) - } - } - }); - }else if(sheet.cssText){ // IE - var matches; - var text = sheet.cssText.toString(); - // unfortunately, using RegExp.exec seems to be flakey - // for looping across multiple lines on IE using the - // global flag, so we have to simulate it - var lines = text.split(/\f|\r|\n/); - for(var i = 0; i < lines.length; i++){ - matches = lines[i].match(/url\(\s*([^\) ]*)\s*\)/i); - if(matches && matches.length){ - handleUrl(matches[1]); - } - } - } - }catch(exp){ - //console.debug("dojox.off.files.slurp stylesheet parse error: " - // + exp.message||exp); - } - }); - - //this.printURLs(); - }, - - _sameLocation: function(url){ - if(!url){ return false; } - - // filter out anchors - if(url.length && url.charAt(0) == "#"){ - return false; - } - - // FIXME: dojo._Url should be made public; - // it's functionality is very useful for - // parsing URLs correctly, which is hard to - // do right - url = new dojo._Url(url); - - // totally relative -- ../../someFile.html - if(!url.scheme && !url.port && !url.host){ - return true; - } - - // scheme relative with port specified -- brad.com:8080 - if(!url.scheme && url.host && url.port - && window.location.hostname == url.host - && window.location.port == url.port){ - return true; - } - - // scheme relative with no-port specified -- brad.com - if(!url.scheme && url.host && !url.port - && window.location.hostname == url.host - && window.location.port == 80){ - return true; - } - - // else we have everything - return window.location.protocol == (url.scheme + ":") - && window.location.hostname == url.host - && (window.location.port == url.port || !window.location.port && !url.port); - }, - - _trimAnchor: function(url){ - return url.replace(/\#.*$/, ""); - }, - - _doRefresh: function(callback, newVersion){ - // get our local server - var localServer; - try{ - localServer = google.gears.factory.create("beta.localserver", "1.0"); - }catch(exp){ - dojo.setObject("google.gears.denied", true); - dojox.off.onFrameworkEvent("coreOperationFailed"); - throw "Google Gears must be allowed to run"; - } - - var storeName = "dot_store_" - + window.location.href.replace(/[^0-9A-Za-z_]/g, "_"); - - // clip at 64 characters, the max length of a resource store name - if(storeName.length >= 64){ - storeName = storeName.substring(0, 63); - } - - // refresh everything by simply removing - // any older stores - localServer.removeStore(storeName); - - // open/create the resource store - localServer.openStore(storeName); - var store = localServer.createStore(storeName); - this._store = store; - - // add our list of files to capture - var self = this; - this._currentFileIndex = 0; - this._cancelID = store.capture(this.listOfURLs, function(url, success, captureId){ - //console.debug("store.capture, url="+url+", success="+success); - if(!success && self.refreshing){ - self._cancelID = null; - self.refreshing = false; - var errorMsgs = []; - errorMsgs.push("Unable to capture: " + url); - callback(true, errorMsgs); - return; - }else if(success){ - self._currentFileIndex++; - } - - if(success && self._currentFileIndex >= self.listOfURLs.length){ - self._cancelID = null; - self.refreshing = false; - if(newVersion){ - dojox.storage.put("oldVersion", newVersion, null, - dojox.off.STORAGE_NAMESPACE); - } - dojox.storage.put("justDebugged", dojo.config.isDebug, null, - dojox.off.STORAGE_NAMESPACE); - callback(false, []); - } - }); - }, - - _getVersionInfo: function(callback){ - var justDebugged = dojox.storage.get("justDebugged", - dojox.off.STORAGE_NAMESPACE); - var oldVersion = dojox.storage.get("oldVersion", - dojox.off.STORAGE_NAMESPACE); - var newVersion = null; - - callback = dojo.hitch(this, callback); - - dojo.xhrGet({ - url: this.versionURL + "?browserbust=" + new Date().getTime(), - timeout: 5 * 1000, - handleAs: "javascript", - error: function(err){ - //console.warn("dojox.off.files._getVersionInfo, err=",err); - dojox.storage.remove("oldVersion", dojox.off.STORAGE_NAMESPACE); - dojox.storage.remove("justDebugged", dojox.off.STORAGE_NAMESPACE); - callback(oldVersion, newVersion, justDebugged); - }, - load: function(data){ - //console.warn("dojox.off.files._getVersionInfo, load=",data); - - // some servers incorrectly return 404's - // as a real page - if(data){ - newVersion = data; - } - - callback(oldVersion, newVersion, justDebugged); - } - }); - } -} - -} diff --git a/includes/js/dojox/off/network_check.txt b/includes/js/dojox/off/network_check.txt deleted file mode 100644 index d00491f..0000000 --- a/includes/js/dojox/off/network_check.txt +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/includes/js/dojox/off/offline.js b/includes/js/dojox/off/offline.js deleted file mode 100644 index 997206e..0000000 --- a/includes/js/dojox/off/offline.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - Copyright (c) 2004-2008, The Dojo Foundation - All Rights Reserved. - - Licensed under the Academic Free License version 2.1 or above OR the - modified BSD license. For more information on Dojo licensing, see: - - http://dojotoolkit.org/book/dojo-book-0-9/introduction/licensing -*/ - -/* - This is a compiled version of Dojo, built for deployment and not for - development. To get an editable version, please visit: - - http://dojotoolkit.org - - for documentation and information on getting the source. -*/ - -if(!dojo._hasResource["dojox.storage.Provider"]){dojo._hasResource["dojox.storage.Provider"]=true;dojo.provide("dojox.storage.Provider");dojo.declare("dojox.storage.Provider",null,{constructor:function(){},SUCCESS:"success",FAILED:"failed",PENDING:"pending",SIZE_NOT_AVAILABLE:"Size not available",SIZE_NO_LIMIT:"No size limit",DEFAULT_NAMESPACE:"default",onHideSettingsUI:null,initialize:function(){console.warn("dojox.storage.initialize not implemented");},isAvailable:function(){console.warn("dojox.storage.isAvailable not implemented");},put:function(_1,_2,_3,_4){console.warn("dojox.storage.put not implemented");},get:function(_5,_6){console.warn("dojox.storage.get not implemented");},hasKey:function(_7,_8){return !!this.get(_7,_8);},getKeys:function(_9){console.warn("dojox.storage.getKeys not implemented");},clear:function(_a){console.warn("dojox.storage.clear not implemented");},remove:function(_b,_c){console.warn("dojox.storage.remove not implemented");},getNamespaces:function(){console.warn("dojox.storage.getNamespaces not implemented");},isPermanent:function(){console.warn("dojox.storage.isPermanent not implemented");},getMaximumSize:function(){console.warn("dojox.storage.getMaximumSize not implemented");},putMultiple:function(_d,_e,_f,_10){console.warn("dojox.storage.putMultiple not implemented");},getMultiple:function(_11,_12){console.warn("dojox.storage.getMultiple not implemented");},removeMultiple:function(_13,_14){console.warn("dojox.storage.remove not implemented");},isValidKeyArray:function(_15){if(_15===null||_15===undefined||!dojo.isArray(_15)){return false;}return !dojo.some(_15,function(key){return !this.isValidKey(key);});},hasSettingsUI:function(){return false;},showSettingsUI:function(){console.warn("dojox.storage.showSettingsUI not implemented");},hideSettingsUI:function(){console.warn("dojox.storage.hideSettingsUI not implemented");},isValidKey:function(_17){if(_17===null||_17===undefined){return false;}return /^[0-9A-Za-z_]*$/.test(_17);},getResourceList:function(){return [];}});}if(!dojo._hasResource["dojox.storage.manager"]){dojo._hasResource["dojox.storage.manager"]=true;dojo.provide("dojox.storage.manager");dojox.storage.manager=new function(){this.currentProvider=null;this.available=false;this.providers=[];this._initialized=false;this._onLoadListeners=[];this.initialize=function(){this.autodetect();};this.register=function(_18,_19){this.providers.push(_19);this.providers[_18]=_19;};this.setProvider=function(_1a){};this.autodetect=function(){if(this._initialized){return;}var _1b=dojo.config["forceStorageProvider"]||false;var _1c;for(var i=0;i6&&i%Nk==4){_60=SubWord(_60);}}for(var t=0;t<4;t++){w[i][t]=w[i-Nk][t]^_60[t];}}return w;};function SubWord(w){for(var i=0;i<4;i++){w[i]=_3c[w[i]];}return w;};function RotWord(w){w[4]=w[0];for(var i=0;i<4;i++){w[i]=w[i+1];}return w;};function AESEncryptCtr(_68,_69,_6a){if(!(_6a==128||_6a==192||_6a==256)){return "";}var _6b=_6a/8;var _6c=new Array(_6b);for(var i=0;i<_6b;i++){_6c[i]=_69.charCodeAt(i)&255;}var key=Cipher(_6c,KeyExpansion(_6c));key=key.concat(key.slice(0,_6b-16));var _6f=16;var _70=new Array(_6f);var _71=(new Date()).getTime();for(var i=0;i<4;i++){_70[i]=(_71>>>i*8)&255;}for(var i=0;i<4;i++){_70[i+4]=(_71/4294967296>>>i*8)&255;}var _72=KeyExpansion(key);var _73=Math.ceil(_68.length/_6f);var _74=new Array(_73);for(var b=0;b<_73;b++){for(var c=0;c<4;c++){_70[15-c]=(b>>>c*8)&255;}for(var c=0;c<4;c++){_70[15-c-4]=(b/4294967296>>>c*8);}var _77=Cipher(_70,_72);var _78=b<_73-1?_6f:(_68.length-1)%_6f+1;var ct="";for(var i=0;i<_78;i++){var _7a=_68.charCodeAt(b*_6f+i);var _7b=_7a^_77[i];ct+=String.fromCharCode(_7b);}_74[b]=escCtrlChars(ct);}var _7c="";for(var i=0;i<8;i++){_7c+=String.fromCharCode(_70[i]);}_7c=escCtrlChars(_7c);return _7c+"-"+_74.join("-");};function AESDecryptCtr(_7d,_7e,_7f){if(!(_7f==128||_7f==192||_7f==256)){return "";}var _80=_7f/8;var _81=new Array(_80);for(var i=0;i<_80;i++){_81[i]=_7e.charCodeAt(i)&255;}var _83=KeyExpansion(_81);var key=Cipher(_81,_83);key=key.concat(key.slice(0,_80-16));var _85=KeyExpansion(key);_7d=_7d.split("-");var _86=16;var _87=new Array(_86);var _88=unescCtrlChars(_7d[0]);for(var i=0;i<8;i++){_87[i]=_88.charCodeAt(i);}var _89=new Array(_7d.length-1);for(var b=1;b<_7d.length;b++){for(var c=0;c<4;c++){_87[15-c]=((b-1)>>>c*8)&255;}for(var c=0;c<4;c++){_87[15-c-4]=((b/4294967296-1)>>>c*8)&255;}var _8c=Cipher(_87,_85);_7d[b]=unescCtrlChars(_7d[b]);var pt="";for(var i=0;i<_7d[b].length;i++){var _8e=_7d[b].charCodeAt(i);var _8f=_8e^_8c[i];pt+=String.fromCharCode(_8f);}_89[b-1]=pt;}return _89.join("");};function escCtrlChars(str){return str.replace(/[\0\t\n\v\f\r\xa0!-]/g,function(c){return "!"+c.charCodeAt(0)+"!";});};function unescCtrlChars(str){return str.replace(/!\d\d?\d?!/g,function(c){return String.fromCharCode(c.slice(1,-1));});};function encrypt(_94,_95){return AESEncryptCtr(_94,_95,256);};function decrypt(_96,_97){return AESDecryptCtr(_96,_97,256);};var cmd=msg.substr(0,4);var arg=msg.substr(5);if(cmd=="encr"){arg=eval("("+arg+")");var _9a=arg.plaintext;var _9b=arg.password;var _9c=encrypt(_9a,_9b);gearsWorkerPool.sendMessage(String(_9c),_3b);}else{if(cmd=="decr"){arg=eval("("+arg+")");var _9d=arg.ciphertext;var _9b=arg.password;var _9c=decrypt(_9d,_9b);gearsWorkerPool.sendMessage(String(_9c),_3b);}}}});}if(!dojo._hasResource["dojox._sql.common"]){dojo._hasResource["dojox._sql.common"]=true;dojo.provide("dojox._sql.common");dojox.sql=new Function("return dojox.sql._exec(arguments);");dojo.mixin(dojox.sql,{dbName:null,debug:(dojo.exists("dojox.sql.debug")?dojox.sql.debug:false),open:function(_9e){if(this._dbOpen&&(!_9e||_9e==this.dbName)){return;}if(!this.dbName){this.dbName="dot_store_"+window.location.href.replace(/[^0-9A-Za-z_]/g,"_");if(this.dbName.length>63){this.dbName=this.dbName.substring(0,63);}}if(!_9e){_9e=this.dbName;}try{this._initDb();this.db.open(_9e);this._dbOpen=true;}catch(exp){throw exp.message||exp;}},close:function(_9f){if(dojo.isIE){return;}if(!this._dbOpen&&(!_9f||_9f==this.dbName)){return;}if(!_9f){_9f=this.dbName;}try{this.db.close(_9f);this._dbOpen=false;}catch(exp){throw exp.message||exp;}},_exec:function(_a0){try{this._initDb();if(!this._dbOpen){this.open();this._autoClose=true;}var sql=null;var _a2=null;var _a3=null;var _a4=dojo._toArray(_a0);sql=_a4.splice(0,1)[0];if(this._needsEncrypt(sql)||this._needsDecrypt(sql)){_a2=_a4.splice(_a4.length-1,1)[0];_a3=_a4.splice(_a4.length-1,1)[0];}if(this.debug){this._printDebugSQL(sql,_a4);}if(this._needsEncrypt(sql)){var _a5=new dojox.sql._SQLCrypto("encrypt",sql,_a3,_a4,_a2);return;}else{if(this._needsDecrypt(sql)){var _a5=new dojox.sql._SQLCrypto("decrypt",sql,_a3,_a4,_a2);return;}}var rs=this.db.execute(sql,_a4);rs=this._normalizeResults(rs);if(this._autoClose){this.close();}return rs;}catch(exp){exp=exp.message||exp;console.debug("SQL Exception: "+exp);if(this._autoClose){try{this.close();}catch(e){console.debug("Error closing database: "+e.message||e);}}throw exp;}},_initDb:function(){if(!this.db){try{this.db=google.gears.factory.create("beta.database","1.0");}catch(exp){dojo.setObject("google.gears.denied",true);dojox.off.onFrameworkEvent("coreOperationFailed");throw "Google Gears must be allowed to run";}}},_printDebugSQL:function(sql,_a8){var msg="dojox.sql(\""+sql+"\"";for(var i=0;i<_a8.length;i++){if(typeof _a8[i]=="string"){msg+=", \""+_a8[i]+"\"";}else{msg+=", "+_a8[i];}}msg+=")";console.debug(msg);},_normalizeResults:function(rs){var _ac=[];if(!rs){return [];}while(rs.isValidRow()){var row={};for(var i=0;i=this._totalCrypto&&this._finishedSpawningCrypto){_d3(this._finalArgs);}}));}}this._finishedSpawningCrypto=true;},_decrypt:function(_d8,_d9,_da,_db){this._totalCrypto=0;this._finishedCrypto=0;this._finishedSpawningCrypto=false;this._finalResultSet=_d8;for(var i=0;i<_d8.length;i++){var row=_d8[i];for(var _de in row){if(_d9=="*"||_d9[_de]){this._totalCrypto++;var _df=row[_de];this._decryptSingleColumn(_de,_df,_da,i,function(_e0){_db(_e0);});}}}this._finishedSpawningCrypto=true;},_stripCryptoSQL:function(sql){sql=sql.replace(/DECRYPT\(\*\)/ig,"*");var _e2=sql.match(/ENCRYPT\([^\)]*\)/ig);if(_e2!=null){for(var i=0;i<_e2.length;i++){var _e4=_e2[i];var _e5=_e4.match(/ENCRYPT\(([^\)]*)\)/i)[1];sql=sql.replace(_e4,_e5);}}_e2=sql.match(/DECRYPT\([^\)]*\)/ig);if(_e2!=null){for(var i=0;i<_e2.length;i++){var _e6=_e2[i];var _e7=_e6.match(/DECRYPT\(([^\)]*)\)/i)[1];sql=sql.replace(_e6,_e7);}}return sql;},_flagEncryptedArgs:function(sql,_e9){var _ea=new RegExp(/([\"][^\"]*\?[^\"]*[\"])|([\'][^\']*\?[^\']*[\'])|(\?)/ig);var _eb;var _ec=0;var _ed=[];while((_eb=_ea.exec(sql))!=null){var _ee=RegExp.lastMatch+"";if(/^[\"\']/.test(_ee)){continue;}var _ef=false;if(/ENCRYPT\([^\)]*$/i.test(RegExp.leftContext)){_ef=true;}_ed[_ec]=_ef;_ec++;}return _ed;},_determineDecryptedColumns:function(sql){var _f1={};if(/DECRYPT\(\*\)/i.test(sql)){_f1="*";}else{var _f2=/DECRYPT\((?:\s*\w*\s*\,?)*\)/ig;var _f3;while(_f3=_f2.exec(sql)){var _f4=new String(RegExp.lastMatch);var _f5=_f4.replace(/DECRYPT\(/i,"");_f5=_f5.replace(/\)/,"");_f5=_f5.split(/\s*,\s*/);dojo.forEach(_f5,function(_f6){if(/\s*\w* AS (\w*)/i.test(_f6)){_f6=_f6.match(/\s*\w* AS (\w*)/i)[1];}_f1[_f6]=true;});}}return _f1;},_decryptSingleColumn:function(_f7,_f8,_f9,_fa,_fb){dojox._sql._crypto.decrypt(_f8,_f9,dojo.hitch(this,function(_fc){this._finalResultSet[_fa][_f7]=_fc;this._finishedCrypto++;if(this._finishedCrypto>=this._totalCrypto&&this._finishedSpawningCrypto){_fb(this._finalResultSet);}}));}});}if(!dojo._hasResource["dojox.sql"]){dojo._hasResource["dojox.sql"]=true;dojo.provide("dojox.sql");}if(!dojo._hasResource["dojox.storage.GearsStorageProvider"]){dojo._hasResource["dojox.storage.GearsStorageProvider"]=true;dojo.provide("dojox.storage.GearsStorageProvider");if(dojo.isGears){(function(){dojo.declare("dojox.storage.GearsStorageProvider",dojox.storage.Provider,{constructor:function(){},TABLE_NAME:"__DOJO_STORAGE",initialized:false,_available:null,initialize:function(){if(dojo.config["disableGearsStorage"]==true){return;}this.TABLE_NAME="__DOJO_STORAGE";try{dojox.sql("CREATE TABLE IF NOT EXISTS "+this.TABLE_NAME+"( "+" namespace TEXT, "+" key TEXT, "+" value TEXT "+")");dojox.sql("CREATE UNIQUE INDEX IF NOT EXISTS namespace_key_index"+" ON "+this.TABLE_NAME+" (namespace, key)");}catch(e){console.debug("dojox.storage.GearsStorageProvider.initialize:",e);this.initialized=false;dojox.storage.manager.loaded();return;}this.initialized=true;dojox.storage.manager.loaded();},isAvailable:function(){return this._available=dojo.isGears;},put:function(key,_fe,_ff,_100){if(this.isValidKey(key)==false){throw new Error("Invalid key given: "+key);}_100=_100||this.DEFAULT_NAMESPACE;if(dojo.isString(_fe)){_fe="string:"+_fe;}else{_fe=dojo.toJson(_fe);}try{dojox.sql("DELETE FROM "+this.TABLE_NAME+" WHERE namespace = ? AND key = ?",_100,key);dojox.sql("INSERT INTO "+this.TABLE_NAME+" VALUES (?, ?, ?)",_100,key,_fe);}catch(e){console.debug("dojox.storage.GearsStorageProvider.put:",e);_ff(this.FAILED,key,e.toString());return;}if(_ff){_ff(dojox.storage.SUCCESS,key,null);}},get:function(key,_102){if(this.isValidKey(key)==false){throw new Error("Invalid key given: "+key);}_102=_102||this.DEFAULT_NAMESPACE;var _103=dojox.sql("SELECT * FROM "+this.TABLE_NAME+" WHERE namespace = ? AND "+" key = ?",_102,key);if(!_103.length){return null;}else{_103=_103[0].value;}if(dojo.isString(_103)&&(/^string:/.test(_103))){_103=_103.substring("string:".length);}else{_103=dojo.fromJson(_103);}return _103;},getNamespaces:function(){var _104=[dojox.storage.DEFAULT_NAMESPACE];var rs=dojox.sql("SELECT namespace FROM "+this.TABLE_NAME+" DESC GROUP BY namespace");for(var i=0;idew){minw=dew;maxw=dbw;}else{maxw=dew;minw=dbw;}var dbh=_143.body.clientHeight;if(dbh>deh){minh=deh;maxh=dbh;}else{maxh=deh;minh=dbh;}w=(maxw>_142.innerWidth)?minw:maxw;h=(maxh>_142.innerHeight)?minh:maxh;}else{if(!dojo.isOpera&&_142.innerWidth){w=_142.innerWidth;h=_142.innerHeight;}else{if(dojo.isIE&&de&&deh){w=dew;h=deh;}else{if(dojo.body().clientWidth){w=dojo.body().clientWidth;h=dojo.body().clientHeight;}}}}var _14f=dojo._docScroll();return {w:w,h:h,l:_14f.x,t:_14f.y};};dijit.placeOnScreen=function(node,pos,_152,_153){var _154=dojo.map(_152,function(_155){return {corner:_155,pos:pos};});return dijit._place(node,_154);};dijit._place=function(node,_157,_158){var view=dijit.getViewport();if(!node.parentNode||String(node.parentNode.tagName).toLowerCase()!="body"){dojo.body().appendChild(node);}var best=null;dojo.some(_157,function(_15b){var _15c=_15b.corner;var pos=_15b.pos;if(_158){_158(node,_15b.aroundCorner,_15c);}var _15e=node.style;var _15f=_15e.display;var _160=_15e.visibility;_15e.visibility="hidden";_15e.display="";var mb=dojo.marginBox(node);_15e.display=_15f;_15e.visibility=_160;var _162=(_15c.charAt(1)=="L"?pos.x:Math.max(view.l,pos.x-mb.w)),_163=(_15c.charAt(0)=="T"?pos.y:Math.max(view.t,pos.y-mb.h)),endX=(_15c.charAt(1)=="L"?Math.min(view.l+view.w,_162+mb.w):pos.x),endY=(_15c.charAt(0)=="T"?Math.min(view.t+view.h,_163+mb.h):pos.y),_166=endX-_162,_167=endY-_163,_168=(mb.w-_166)+(mb.h-_167);if(best==null||_1680){for(var i=0;i0){for(var i=0;i","Function VBGetSwfVer(i)"," on error resume next"," Dim swControl, swVersion"," swVersion = 0"," set swControl = CreateObject(\"ShockwaveFlash.ShockwaveFlash.\" + CStr(i))"," if (IsObject(swControl)) then"," swVersion = swControl.GetVariable(\"$version\")"," end if"," VBGetSwfVer = swVersion","End Function",""].join("\r\n"));}this._detectVersion();};dojox.flash.Info.prototype={version:-1,versionMajor:-1,versionMinor:-1,versionRevision:-1,capable:false,installing:false,isVersionOrAbove:function(_17a,_17b,_17c){_17c=parseFloat("."+_17c);if(this.versionMajor>=_17a&&this.versionMinor>=_17b&&this.versionRevision>=_17c){return true;}else{return false;}},_detectVersion:function(){var _17d;for(var _17e=25;_17e>0;_17e--){if(dojo.isIE){_17d=VBGetSwfVer(_17e);}else{_17d=this._JSFlashInfo(_17e);}if(_17d==-1){this.capable=false;return;}else{if(_17d!=0){var _17f;if(dojo.isIE){var _180=_17d.split(" ");var _181=_180[1];_17f=_181.split(",");}else{_17f=_17d.split(".");}this.versionMajor=_17f[0];this.versionMinor=_17f[1];this.versionRevision=_17f[2];var _182=this.versionMajor+"."+this.versionRevision;this.version=parseFloat(_182);this.capable=true;break;}}}},_JSFlashInfo:function(_183){if(navigator.plugins!=null&&navigator.plugins.length>0){if(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]){var _184=navigator.plugins["Shockwave Flash 2.0"]?" 2.0":"";var _185=navigator.plugins["Shockwave Flash"+_184].description;var _186=_185.split(" ");var _187=_186[2].split(".");var _188=_187[0];var _189=_187[1];if(_186[3]!=""){var _18a=_186[3].split("r");}else{var _18a=_186[4].split("r");}var _18b=_18a[1]>0?_18a[1]:0;var _18c=_188+"."+_189+"."+_18b;return _18c;}}return -1;}};dojox.flash.Embed=function(_18d){this._visible=_18d;};dojox.flash.Embed.prototype={width:215,height:138,id:"flashObject",_visible:true,protocol:function(){switch(window.location.protocol){case "https:":return "https";break;default:return "http";break;}},write:function(_18e){var _18f="";_18f+=("width: "+this.width+"px; ");_18f+=("height: "+this.height+"px; ");if(!this._visible){_18f+="position: absolute; z-index: 10000; top: -1000px; left: -1000px; ";}var _190;var _191=dojox.flash.url;var _192=_191;var _193=_191;var _194=dojo.baseUrl;if(_18e){var _195=escape(window.location);document.title=document.title.slice(0,47)+" - Flash Player Installation";var _196=escape(document.title);_192+="?MMredirectURL="+_195+"&MMplayerType=ActiveX"+"&MMdoctitle="+_196+"&baseUrl="+escape(_194);_193+="?MMredirectURL="+_195+"&MMplayerType=PlugIn"+"&baseUrl="+escape(_194);}else{_192+="?cachebust="+new Date().getTime();}if(_193.indexOf("?")==-1){_193+="?baseUrl="+escape(_194);}else{_193+="&baseUrl="+escape(_194);}_190="\n "+"\n "+"\n "+"\n "+"\n "+"\n"+"\n";dojo.connect(dojo,"loaded",dojo.hitch(this,function(){var div=document.createElement("div");div.setAttribute("id",this.id+"Container");div.setAttribute("style",_18f);div.innerHTML=_190;var body=document.getElementsByTagName("body");if(!body||!body.length){throw new Error("No body tag for this page");}body=body[0];body.appendChild(div);}));},get:function(){if(dojo.isIE||dojo.isSafari){return document.getElementById(this.id);}else{return document[this.id+"Embed"];}},setVisible:function(_199){var _19a=dojo.byId(this.id+"Container");if(_199==true){_19a.style.position="absolute";_19a.style.visibility="visible";}else{_19a.style.position="absolute";_19a.style.x="-1000px";_19a.style.y="-1000px";_19a.style.visibility="hidden";}},center:function(){var _19b=this.width;var _19c=this.height;var _19d=dijit.getViewport();var x=_19d.l+(_19d.w-_19b)/2;var y=_19d.t+(_19d.h-_19c)/2;var _1a0=dojo.byId(this.id+"Container");_1a0.style.top=y+"px";_1a0.style.left=x+"px";}};dojox.flash.Communicator=function(){};dojox.flash.Communicator.prototype={_addExternalInterfaceCallback:function(_1a1){var _1a2=dojo.hitch(this,function(){var _1a3=new Array(arguments.length);for(var i=0;i/g,">");data=data.replace("\\","&custom_backslash;");data=data.replace(/\0/g,"\\0");data=data.replace(/\"/g,""");return data;},_decodeData:function(data){if(data&&data.length&&typeof data!="string"){data=data[0];}if(!data||typeof data!="string"){return data;}data=data.replace(/\&custom_lt\;/g,"<");data=data.replace(/\&custom_gt\;/g,">");data=data.replace(/\&custom_backslash\;/g,"\\");data=data.replace(/\\0/g,"");return data;},_execFlash:function(_1a9,_1aa){var _1ab=dojox.flash.obj.get();_1aa=(_1aa)?_1aa:[];for(var i=0;i<_1aa;i++){if(typeof _1aa[i]=="string"){_1aa[i]=this._encodeData(_1aa[i]);}}var _1ad=function(){return eval(_1ab.CallFunction(""+__flash__argumentsToXML(_1aa,0)+""));};var _1ae=_1ad.call(_1aa);if(typeof _1ae=="string"){_1ae=this._decodeData(_1ae);}return _1ae;}};dojox.flash.Install=function(){};dojox.flash.Install.prototype={needed:function(){if(dojox.flash.info.capable==false){return true;}if(!dojox.flash.info.isVersionOrAbove(8,0,0)){return true;}return false;},install:function(){dojox.flash.info.installing=true;dojox.flash.installing();if(dojox.flash.info.capable==false){var _1af=new dojox.flash.Embed(false);_1af.write();}else{if(dojox.flash.info.isVersionOrAbove(6,0,65)){var _1af=new dojox.flash.Embed(false);_1af.write(true);_1af.setVisible(true);_1af.center();}else{alert("This content requires a more recent version of the Macromedia "+" Flash Player.");window.location.href=+dojox.flash.Embed.protocol()+"://www.macromedia.com/go/getflashplayer";}}},_onInstallStatus:function(msg){if(msg=="Download.Complete"){dojox.flash._initialize();}else{if(msg=="Download.Cancelled"){alert("This content requires a more recent version of the Macromedia "+" Flash Player.");window.location.href=dojox.flash.Embed.protocol()+"://www.macromedia.com/go/getflashplayer";}else{if(msg=="Download.Failed"){alert("There was an error downloading the Flash Player update. "+"Please try again later, or visit macromedia.com to download "+"the latest version of the Flash plugin.");}}}}};dojox.flash.info=new dojox.flash.Info();}if(!dojo._hasResource["dojox.flash"]){dojo._hasResource["dojox.flash"]=true;dojo.provide("dojox.flash");}if(!dojo._hasResource["dojox.storage.FlashStorageProvider"]){dojo._hasResource["dojox.storage.FlashStorageProvider"]=true;dojo.provide("dojox.storage.FlashStorageProvider");dojo.declare("dojox.storage.FlashStorageProvider",dojox.storage.Provider,{initialized:false,_available:null,_statusHandler:null,_flashReady:false,_pageReady:false,initialize:function(){if(dojo.config["disableFlashStorage"]==true){return;}dojox.flash.addLoadedListener(dojo.hitch(this,function(){this._flashReady=true;if(this._flashReady&&this._pageReady){this._loaded();}}));var _1b1=dojo.moduleUrl("dojox","storage/Storage.swf").toString();dojox.flash.setSwf(_1b1,false);dojo.connect(dojo,"loaded",this,function(){this._pageReady=true;if(this._flashReady&&this._pageReady){this._loaded();}});},setFlushDelay:function(_1b2){if(_1b2===null||typeof _1b2==="undefined"||isNaN(_1b2)){throw new Error("Invalid argunment: "+_1b2);}dojox.flash.comm.setFlushDelay(String(_1b2));},getFlushDelay:function(){return Number(dojox.flash.comm.getFlushDelay());},flush:function(_1b3){if(_1b3==null||typeof _1b3=="undefined"){_1b3=dojox.storage.DEFAULT_NAMESPACE;}dojox.flash.comm.flush(_1b3);},isAvailable:function(){return (this._available=!dojo.config["disableFlashStorage"]);},put:function(key,_1b5,_1b6,_1b7){if(!this.isValidKey(key)){throw new Error("Invalid key given: "+key);}if(!_1b7){_1b7=dojox.storage.DEFAULT_NAMESPACE;}if(!this.isValidKey(_1b7)){throw new Error("Invalid namespace given: "+_1b7);}this._statusHandler=_1b6;if(dojo.isString(_1b5)){_1b5="string:"+_1b5;}else{_1b5=dojo.toJson(_1b5);}dojox.flash.comm.put(key,_1b5,_1b7);},putMultiple:function(keys,_1b9,_1ba,_1bb){if(!this.isValidKeyArray(keys)||!_1b9 instanceof Array||keys.length!=_1b9.length){throw new Error("Invalid arguments: keys = ["+keys+"], values = ["+_1b9+"]");}if(!_1bb){_1bb=dojox.storage.DEFAULT_NAMESPACE;}if(!this.isValidKey(_1bb)){throw new Error("Invalid namespace given: "+_1bb);}this._statusHandler=_1ba;var _1bc=keys.join(",");var _1bd=[];for(var i=0;i<_1b9.length;i++){if(dojo.isString(_1b9[i])){_1b9[i]="string:"+_1b9[i];}else{_1b9[i]=dojo.toJson(_1b9[i]);}_1bd[i]=_1b9[i].length;}var _1bf=_1b9.join("");var _1c0=_1bd.join(",");dojox.flash.comm.putMultiple(_1bc,_1bf,_1c0,this.namespace);},get:function(key,_1c2){if(!this.isValidKey(key)){throw new Error("Invalid key given: "+key);}if(!_1c2){_1c2=dojox.storage.DEFAULT_NAMESPACE;}if(!this.isValidKey(_1c2)){throw new Error("Invalid namespace given: "+_1c2);}var _1c3=dojox.flash.comm.get(key,_1c2);if(_1c3==""){return null;}return this._destringify(_1c3);},getMultiple:function(keys,_1c5){if(!this.isValidKeyArray(keys)){throw new ("Invalid key array given: "+keys);}if(!_1c5){_1c5=dojox.storage.DEFAULT_NAMESPACE;}if(!this.isValidKey(_1c5)){throw new Error("Invalid namespace given: "+_1c5);}var _1c6=keys.join(",");var _1c7=dojox.flash.comm.getMultiple(_1c6,this.namespace);var _1c8=eval("("+_1c7+")");for(var i=0;i<_1c8.length;i++){_1c8[i]=(_1c8[i]=="")?null:this._destringify(_1c8[i]);}return _1c8;},_destringify:function(_1ca){if(dojo.isString(_1ca)&&(/^string:/.test(_1ca))){_1ca=_1ca.substring("string:".length);}else{_1ca=dojo.fromJson(_1ca);}return _1ca;},getKeys:function(_1cb){if(!_1cb){_1cb=dojox.storage.DEFAULT_NAMESPACE;}if(!this.isValidKey(_1cb)){throw new Error("Invalid namespace given: "+_1cb);}var _1cc=dojox.flash.comm.getKeys(_1cb);if(_1cc==null||_1cc=="null"){_1cc="";}_1cc=_1cc.split(",");_1cc.sort();return _1cc;},getNamespaces:function(){var _1cd=dojox.flash.comm.getNamespaces();if(_1cd==null||_1cd=="null"){_1cd=dojox.storage.DEFAULT_NAMESPACE;}_1cd=_1cd.split(",");_1cd.sort();return _1cd;},clear:function(_1ce){if(!_1ce){_1ce=dojox.storage.DEFAULT_NAMESPACE;}if(!this.isValidKey(_1ce)){throw new Error("Invalid namespace given: "+_1ce);}dojox.flash.comm.clear(_1ce);},remove:function(key,_1d0){if(!_1d0){_1d0=dojox.storage.DEFAULT_NAMESPACE;}if(!this.isValidKey(_1d0)){throw new Error("Invalid namespace given: "+_1d0);}dojox.flash.comm.remove(key,_1d0);},removeMultiple:function(keys,_1d2){if(!this.isValidKeyArray(keys)){dojo.raise("Invalid key array given: "+keys);}if(!_1d2){_1d2=dojox.storage.DEFAULT_NAMESPACE;}if(!this.isValidKey(_1d2)){throw new Error("Invalid namespace given: "+_1d2);}var _1d3=keys.join(",");dojox.flash.comm.removeMultiple(_1d3,this.namespace);},isPermanent:function(){return true;},getMaximumSize:function(){return dojox.storage.SIZE_NO_LIMIT;},hasSettingsUI:function(){return true;},showSettingsUI:function(){dojox.flash.comm.showSettings();dojox.flash.obj.setVisible(true);dojox.flash.obj.center();},hideSettingsUI:function(){dojox.flash.obj.setVisible(false);if(dojo.isFunction(dojox.storage.onHideSettingsUI)){dojox.storage.onHideSettingsUI.call(null);}},getResourceList:function(){return [];},_loaded:function(){this._allNamespaces=this.getNamespaces();this.initialized=true;dojox.storage.manager.loaded();},_onStatus:function(_1d4,key,_1d6){var ds=dojox.storage;var dfo=dojox.flash.obj;if(_1d4==ds.PENDING){dfo.center();dfo.setVisible(true);}else{dfo.setVisible(false);}if(ds._statusHandler){ds._statusHandler.call(null,_1d4,key,_1d6);}}});dojox.storage.manager.register("dojox.storage.FlashStorageProvider",new dojox.storage.FlashStorageProvider());}if(!dojo._hasResource["dojox.storage._common"]){dojo._hasResource["dojox.storage._common"]=true;dojo.provide("dojox.storage._common");dojox.storage.manager.initialize();}if(!dojo._hasResource["dojox.storage"]){dojo._hasResource["dojox.storage"]=true;dojo.provide("dojox.storage");}if(!dojo._hasResource["dojox.off.files"]){dojo._hasResource["dojox.off.files"]=true;dojo.provide("dojox.off.files");dojox.off.files={versionURL:"version.js",listOfURLs:[],refreshing:false,_cancelID:null,_error:false,_errorMessages:[],_currentFileIndex:0,_store:null,_doSlurp:false,slurp:function(){this._doSlurp=true;},cache:function(_1d9){if(dojo.isString(_1d9)){var url=this._trimAnchor(_1d9+"");if(!this.isAvailable(url)){this.listOfURLs.push(url);}}else{if(_1d9 instanceof dojo._Url){var url=this._trimAnchor(_1d9.uri);if(!this.isAvailable(url)){this.listOfURLs.push(url);}}else{dojo.forEach(_1d9,function(url){url=this._trimAnchor(url);if(!this.isAvailable(url)){this.listOfURLs.push(url);}},this);}}},printURLs:function(){console.debug("The following URLs are cached for offline use:");dojo.forEach(this.listOfURLs,function(i){console.debug(i);});},remove:function(url){for(var i=0;i=64){_1f9=_1f9.substring(0,63);}_1f8.removeStore(_1f9);_1f8.openStore(_1f9);var _1fa=_1f8.createStore(_1f9);this._store=_1fa;var self=this;this._currentFileIndex=0;this._cancelID=_1fa.capture(this.listOfURLs,function(url,_1fd,_1fe){if(!_1fd&&self.refreshing){self._cancelID=null;self.refreshing=false;var _1ff=[];_1ff.push("Unable to capture: "+url);_1f6(true,_1ff);return;}else{if(_1fd){self._currentFileIndex++;}}if(_1fd&&self._currentFileIndex>=self.listOfURLs.length){self._cancelID=null;self.refreshing=false;if(_1f7){dojox.storage.put("oldVersion",_1f7,null,dojox.off.STORAGE_NAMESPACE);}dojox.storage.put("justDebugged",dojo.config.isDebug,null,dojox.off.STORAGE_NAMESPACE);_1f6(false,[]);}});},_getVersionInfo:function(_200){var _201=dojox.storage.get("justDebugged",dojox.off.STORAGE_NAMESPACE);var _202=dojox.storage.get("oldVersion",dojox.off.STORAGE_NAMESPACE);var _203=null;_200=dojo.hitch(this,_200);dojo.xhrGet({url:this.versionURL+"?browserbust="+new Date().getTime(),timeout:5*1000,handleAs:"javascript",error:function(err){dojox.storage.remove("oldVersion",dojox.off.STORAGE_NAMESPACE);dojox.storage.remove("justDebugged",dojox.off.STORAGE_NAMESPACE);_200(_202,_203,_201);},load:function(data){if(data){_203=data;}_200(_202,_203,_201);}});}};}if(!dojo._hasResource["dojox.off.sync"]){dojo._hasResource["dojox.off.sync"]=true;dojo.provide("dojox.off.sync");dojo.mixin(dojox.off.sync,{isSyncing:false,cancelled:false,successful:true,details:[],error:false,actions:null,autoSync:true,onSync:function(type){},synchronize:function(){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(){if(!this.isSyncing){return;}this.cancelled=true;if(dojox.off.files.refreshing){dojox.off.files.abortRefresh();}this.onSync("cancel");},finishedDownloading:function(_207,_208){if(typeof _207=="undefined"){_207=true;}if(!_207){this.successful=false;this.details.push(_208);this.error=true;}this.finished();},start:function(){if(this.cancelled){this.finished();return;}this.onSync("start");this.refreshFiles();},refreshFiles:function(){if(this.cancelled){this.finished();return;}this.onSync("refreshFiles");dojox.off.files.refresh(dojo.hitch(this,function(_209,_20a){if(_209){this.error=true;this.successful=false;for(var i=0;i<_20a.length;i++){this.details.push(_20a[i]);}}this.upload();}));},upload:function(){if(this.cancelled){this.finished();return;}this.onSync("upload");dojo.connect(this.actions,"onReplayFinished",this,this.download);this.actions.replay();},download:function(){if(this.cancelled){this.finished();return;}this.onSync("download");},finished:function(){this.isSyncing=false;this.successful=(!this.cancelled&&!this.error);this.onSync("finished");},_save:function(_20c){this.actions._save(function(){_20c();});},_load:function(_20d){this.actions._load(function(){_20d();});}});dojo.declare("dojox.off.sync.ActionLog",null,{entries:[],reasonHalted:null,isReplaying:false,autoSave:true,add:function(_20e){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(_20e);if(this.autoSave){this._save();}},onReplay:function(_20f,_210){},length:function(){return this.entries.length;},haltReplay:function(_211){if(!this.isReplaying){return;}if(_211){this.reasonHalted=_211.toString();}if(this.autoSave){var self=this;this._save(function(){self.isReplaying=false;self.onReplayFinished();});}else{this.isReplaying=false;this.onReplayFinished();}},continueReplay:function(){if(!this.isReplaying){return;}this.entries.shift();if(!this.entries.length){if(this.autoSave){var self=this;this._save(function(){self.isReplaying=false;self.onReplayFinished();});return;}else{this.isReplaying=false;this.onReplayFinished();return;}}var _214=this.entries[0];this.onReplay(_214,this);},clear:function(){if(this.isReplaying){return;}this.entries=[];if(this.autoSave){this._save();}},replay:function(){if(this.isReplaying){return;}this.reasonHalted=null;if(!this.entries.length){this.onReplayFinished();return;}this.isReplaying=true;var _215=this.entries[0];this.onReplay(_215,this);},onReplayFinished:function(){},toString:function(){var _216="";_216+="[";for(var i=0;i";html+=dojox.off.sync.details[i];html+="";}html+="\n";html+=""+"Close Window"+"\n";html+="";var _24c="height=400,width=600,resizable=true,"+"scrollbars=true,toolbar=no,menubar=no,"+"location=no,directories=no,dependent=yes";var _24d=window.open("","SyncDetails",_24c);if(!_24d){alert("Please allow popup windows for this domain; can't display sync details window");return;}_24d.document.open();_24d.document.write(html);_24d.document.close();if(_24d.focus){_24d.focus();}},_cancel:function(evt){evt.preventDefault();evt.stopPropagation();dojox.off.sync.cancel();},_needsBrowserRestart:function(){var _24f=dojo.byId("dot-widget-browser-restart");if(_24f){dojo.addClass(_24f,"dot-needs-browser-restart");}var _250=dojo.byId("dot-widget-browser-restart-app-name");if(_250){_250.innerHTML="";_250.appendChild(document.createTextNode(this.appName));}var _251=dojo.byId("dot-sync-status");if(_251){_251.style.display="none";}},_showNeedsOfflineCache:function(){var _252=dojo.byId("dot-widget-container");if(_252){dojo.addClass(_252,"dot-needs-offline-cache");}},_hideNeedsOfflineCache:function(){var _253=dojo.byId("dot-widget-container");if(_253){dojo.removeClass(_253,"dot-needs-offline-cache");}},_initMainEvtHandlers:function(){var _254=dojo.byId("dot-sync-details-button");if(_254){dojo.connect(_254,"onclick",this,this._showDetails);}var _255=dojo.byId("dot-sync-cancel-button");if(_255){dojo.connect(_255,"onclick",this,this._cancel);}},_setOfflineEnabled:function(_256){var _257=[];_257.push(dojo.byId("dot-sync-status"));for(var i=0;i<_257.length;i++){if(_257[i]){_257[i].style.visibility=(_256?"visible":"hidden");}}},_syncFinished:function(){this._updateSyncUI();var _259=dojo.byId("dot-success-checkmark");var _25a=dojo.byId("dot-sync-details");if(dojox.off.sync.successful==true){this._setSyncMessage("Sync Successful");if(_259){_259.style.display="inline";}}else{if(dojox.off.sync.cancelled==true){this._setSyncMessage("Sync Cancelled");if(_259){_259.style.display="none";}}else{this._setSyncMessage("Sync Error");var _25b=dojo.byId("dot-sync-messages");if(_25b){dojo.addClass(_25b,"dot-sync-error");}if(_259){_259.style.display="none";}}}if(dojox.off.sync.details.length&&_25a){_25a.style.display="inline";}},_onFrameworkEvent:function(type,_25d){if(type=="save"){if(_25d.status==dojox.storage.FAILED&&!_25d.isCoreSave){alert("Please increase the amount of local storage available "+"to this application");if(dojox.storage.hasSettingsUI()){dojox.storage.showSettingsUI();}}}else{if(type=="coreOperationFailed"){console.log("Application does not have permission to use Dojo Offline");if(!this._userInformed){alert("This application will not work if Google Gears is not allowed to run");this._userInformed=true;}}else{if(type=="offlineCacheInstalled"){this._hideNeedsOfflineCache();if(dojox.off.hasOfflineCache==true&&dojox.off.browserRestart==true){this._needsBrowserRestart();return;}else{var _25e=dojo.byId("dot-widget-browser-restart");if(_25e){_25e.style.display="none";}}this._updateSyncUI();this._initMainEvtHandlers();this._setOfflineEnabled(dojox.off.enabled);this._testNet();}}}},_onSync:function(type){switch(type){case "start":this._updateSyncUI();break;case "refreshFiles":this._setSyncMessage("Downloading UI...");break;case "upload":this._setSyncMessage("Uploading new data...");break;case "download":this._setSyncMessage("Downloading new data...");break;case "finished":this._syncFinished();break;case "cancel":this._setSyncMessage("Canceling Sync...");break;default:dojo.warn("Programming error: "+"Unknown sync type in dojox.off.ui: "+type);break;}},_onNetwork:function(type){if(!this._initialized){return;}this._updateNetIndicator();if(type=="offline"){this._setSyncMessage("You are working offline");var _261=dojo.byId("dot-sync-details");if(_261){_261.style.display="none";}this._updateSyncUI();}else{if(dojox.off.sync.autoSync){if(dojo.isAIR){window.setTimeout(function(){dojox.off.sync.synchronize();},1000);}else{window.setTimeout(dojox._scopeName+".off.sync.synchronize()",1000);}}}}});dojo.connect(dojox.off,"onFrameworkEvent",dojox.off.ui,"_onFrameworkEvent");dojo.connect(dojox.off,"onLoad",dojox.off.ui,dojox.off.ui._initialize);}if(!dojo._hasResource["dojox.off.offline"]){dojo._hasResource["dojox.off.offline"]=true;dojo.provide("dojox.off.offline");} diff --git a/includes/js/dojox/off/offline.js.uncompressed.js b/includes/js/dojox/off/offline.js.uncompressed.js deleted file mode 100644 index aa2866d..0000000 --- a/includes/js/dojox/off/offline.js.uncompressed.js +++ /dev/null @@ -1,5910 +0,0 @@ -/* - Copyright (c) 2004-2008, The Dojo Foundation - All Rights Reserved. - - Licensed under the Academic Free License version 2.1 or above OR the - modified BSD license. For more information on Dojo licensing, see: - - http://dojotoolkit.org/book/dojo-book-0-9/introduction/licensing -*/ - -/* - This is a compiled version of Dojo, built for deployment and not for - development. To get an editable version, please visit: - - http://dojotoolkit.org - - for documentation and information on getting the source. -*/ - -if(!dojo._hasResource["dojox.storage.Provider"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojox.storage.Provider"] = true; -dojo.provide("dojox.storage.Provider"); - -dojo.declare("dojox.storage.Provider", null, { - // summary: A singleton for working with dojox.storage. - // description: - // dojox.storage exposes the current available storage provider on this - // platform. It gives you methods such as dojox.storage.put(), - // dojox.storage.get(), etc. - // - // For more details on dojox.storage, see the primary documentation - // page at - // http://manual.dojotoolkit.org/storage.html - // - // Note for storage provider developers who are creating subclasses- - // This is the base class for all storage providers Specific kinds of - // Storage Providers should subclass this and implement these methods. - // You should avoid initialization in storage provider subclass's - // constructor; instead, perform initialization in your initialize() - // method. - constructor: function(){ - }, - - // SUCCESS: String - // Flag that indicates a put() call to a - // storage provider was succesful. - SUCCESS: "success", - - // FAILED: String - // Flag that indicates a put() call to - // a storage provider failed. - FAILED: "failed", - - // PENDING: String - // Flag that indicates a put() call to a - // storage provider is pending user approval. - PENDING: "pending", - - // SIZE_NOT_AVAILABLE: String - // Returned by getMaximumSize() if this storage provider can not determine - // the maximum amount of data it can support. - SIZE_NOT_AVAILABLE: "Size not available", - - // SIZE_NO_LIMIT: String - // Returned by getMaximumSize() if this storage provider has no theoretical - // limit on the amount of data it can store. - SIZE_NO_LIMIT: "No size limit", - - // DEFAULT_NAMESPACE: String - // The namespace for all storage operations. This is useful if several - // applications want access to the storage system from the same domain but - // want different storage silos. - DEFAULT_NAMESPACE: "default", - - // onHideSettingsUI: Function - // If a function is assigned to this property, then when the settings - // provider's UI is closed this function is called. Useful, for example, - // if the user has just cleared out all storage for this provider using - // the settings UI, and you want to update your UI. - onHideSettingsUI: null, - - initialize: function(){ - // summary: - // Allows this storage provider to initialize itself. This is - // called after the page has finished loading, so you can not do - // document.writes(). Storage Provider subclasses should initialize - // themselves inside of here rather than in their function - // constructor. - console.warn("dojox.storage.initialize not implemented"); - }, - - isAvailable: function(){ /*Boolean*/ - // summary: - // Returns whether this storage provider is available on this - // platform. - console.warn("dojox.storage.isAvailable not implemented"); - }, - - put: function( /*string*/ key, - /*object*/ value, - /*function*/ resultsHandler, - /*string?*/ namespace){ - // summary: - // Puts a key and value into this storage system. - // description: - // Example- - // var resultsHandler = function(status, key, message){ - // alert("status="+status+", key="+key+", message="+message); - // }; - // dojox.storage.put("test", "hello world", resultsHandler); - // - // Important note: if you are using Dojo Storage in conjunction with - // Dojo Offline, then you don't need to provide - // a resultsHandler; this is because for Dojo Offline we - // use Google Gears to persist data, which has unlimited data - // once the user has given permission. If you are using Dojo - // Storage apart from Dojo Offline, then under the covers hidden - // Flash might be used, which is both asychronous and which might - // get denied; in this case you must provide a resultsHandler. - // key: - // A string key to use when retrieving this value in the future. - // value: - // A value to store; this can be any JavaScript type. - // resultsHandler: - // A callback function that will receive three arguments. The - // first argument is one of three values: dojox.storage.SUCCESS, - // dojox.storage.FAILED, or dojox.storage.PENDING; these values - // determine how the put request went. In some storage systems - // users can deny a storage request, resulting in a - // dojox.storage.FAILED, while in other storage systems a storage - // request must wait for user approval, resulting in a - // dojox.storage.PENDING status until the request is either - // approved or denied, resulting in another call back with - // dojox.storage.SUCCESS. - // The second argument in the call back is the key name that was being stored. - // The third argument in the call back is an optional message that - // details possible error messages that might have occurred during - // the storage process. - // namespace: - // Optional string namespace that this value will be placed into; - // if left off, the value will be placed into dojox.storage.DEFAULT_NAMESPACE - - console.warn("dojox.storage.put not implemented"); - }, - - get: function(/*string*/ key, /*string?*/ namespace){ /*Object*/ - // summary: - // Gets the value with the given key. Returns null if this key is - // not in the storage system. - // key: - // A string key to get the value of. - // namespace: - // Optional string namespace that this value will be retrieved from; - // if left off, the value will be retrieved from dojox.storage.DEFAULT_NAMESPACE - // return: Returns any JavaScript object type; null if the key is not present - console.warn("dojox.storage.get not implemented"); - }, - - hasKey: function(/*string*/ key, /*string?*/ namespace){ - // summary: Determines whether the storage has the given key. - return !!this.get(key, namespace); // Boolean - }, - - getKeys: function(/*string?*/ namespace){ /*Array*/ - // summary: Enumerates all of the available keys in this storage system. - // return: Array of available keys - console.warn("dojox.storage.getKeys not implemented"); - }, - - clear: function(/*string?*/ namespace){ - // summary: - // Completely clears this storage system of all of it's values and - // keys. If 'namespace' is provided just clears the keys in that - // namespace. - console.warn("dojox.storage.clear not implemented"); - }, - - remove: function(/*string*/ key, /*string?*/ namespace){ - // summary: Removes the given key from this storage system. - console.warn("dojox.storage.remove not implemented"); - }, - - getNamespaces: function(){ /*string[]*/ - console.warn("dojox.storage.getNamespaces not implemented"); - }, - - isPermanent: function(){ /*Boolean*/ - // summary: - // Returns whether this storage provider's values are persisted - // when this platform is shutdown. - console.warn("dojox.storage.isPermanent not implemented"); - }, - - getMaximumSize: function(){ /* mixed */ - // summary: The maximum storage allowed by this provider - // returns: - // Returns the maximum storage size - // supported by this provider, in - // thousands of bytes (i.e., if it - // returns 60 then this means that 60K - // of storage is supported). - // - // If this provider can not determine - // it's maximum size, then - // dojox.storage.SIZE_NOT_AVAILABLE is - // returned; if there is no theoretical - // limit on the amount of storage - // this provider can return, then - // dojox.storage.SIZE_NO_LIMIT is - // returned - console.warn("dojox.storage.getMaximumSize not implemented"); - }, - - putMultiple: function( /*array*/ keys, - /*array*/ values, - /*function*/ resultsHandler, - /*string?*/ namespace){ - // summary: - // Puts multiple keys and values into this storage system. - // description: - // Example- - // var resultsHandler = function(status, key, message){ - // alert("status="+status+", key="+key+", message="+message); - // }; - // dojox.storage.put(["test"], ["hello world"], resultsHandler); - // - // Important note: if you are using Dojo Storage in conjunction with - // Dojo Offline, then you don't need to provide - // a resultsHandler; this is because for Dojo Offline we - // use Google Gears to persist data, which has unlimited data - // once the user has given permission. If you are using Dojo - // Storage apart from Dojo Offline, then under the covers hidden - // Flash might be used, which is both asychronous and which might - // get denied; in this case you must provide a resultsHandler. - // keys: - // An array of string keys to use when retrieving this value in the future, - // one per value to be stored - // values: - // An array of values to store; this can be any JavaScript type, though the - // performance of plain strings is considerably better - // resultsHandler: - // A callback function that will receive three arguments. The - // first argument is one of three values: dojox.storage.SUCCESS, - // dojox.storage.FAILED, or dojox.storage.PENDING; these values - // determine how the put request went. In some storage systems - // users can deny a storage request, resulting in a - // dojox.storage.FAILED, while in other storage systems a storage - // request must wait for user approval, resulting in a - // dojox.storage.PENDING status until the request is either - // approved or denied, resulting in another call back with - // dojox.storage.SUCCESS. - // The second argument in the call back is the key name that was being stored. - // The third argument in the call back is an optional message that - // details possible error messages that might have occurred during - // the storage process. - // namespace: - // Optional string namespace that this value will be placed into; - // if left off, the value will be placed into dojox.storage.DEFAULT_NAMESPACE - - console.warn("dojox.storage.putMultiple not implemented"); - // JAC: We could implement a 'default' puMultiple here by just doing - // each put individually - }, - - getMultiple: function(/*array*/ keys, /*string?*/ namespace){ /*Object*/ - // summary: - // Gets the valuse corresponding to each of the given keys. - // Returns a null array element for each given key that is - // not in the storage system. - // keys: - // An array of string keys to get the value of. - // namespace: - // Optional string namespace that this value will be retrieved from; - // if left off, the value will be retrieved from dojox.storage.DEFAULT_NAMESPACE - // return: Returns any JavaScript object type; null if the key is not present - - console.warn("dojox.storage.getMultiple not implemented"); - // JAC: We could implement a 'default' getMultiple here by just - // doing each get individually - }, - - removeMultiple: function(/*array*/ keys, /*string?*/ namespace) { - // summary: Removes the given keys from this storage system. - - // JAC: We could implement a 'default' removeMultiple here by just - // doing each remove individually - console.warn("dojox.storage.remove not implemented"); - }, - - isValidKeyArray: function( keys) { - if(keys === null || keys === undefined || !dojo.isArray(keys)){ - return false; - } - - // JAC: This could be optimized by running the key validity test - // directly over a joined string - return !dojo.some(keys, function(key){ - return !this.isValidKey(key); - }); // Boolean - }, - - hasSettingsUI: function(){ /*Boolean*/ - // summary: Determines whether this provider has a settings UI. - return false; - }, - - showSettingsUI: function(){ - // summary: If this provider has a settings UI, determined - // by calling hasSettingsUI(), it is shown. - console.warn("dojox.storage.showSettingsUI not implemented"); - }, - - hideSettingsUI: function(){ - // summary: If this provider has a settings UI, hides it. - console.warn("dojox.storage.hideSettingsUI not implemented"); - }, - - isValidKey: function(/*string*/ keyName){ /*Boolean*/ - // summary: - // Subclasses can call this to ensure that the key given is valid - // in a consistent way across different storage providers. We use - // the lowest common denominator for key values allowed: only - // letters, numbers, and underscores are allowed. No spaces. - if(keyName === null || keyName === undefined){ - return false; - } - - return /^[0-9A-Za-z_]*$/.test(keyName); - }, - - getResourceList: function(){ /* Array[] */ - // summary: - // Returns a list of URLs that this - // storage provider might depend on. - // description: - // This method returns a list of URLs that this - // storage provider depends on to do its work. - // This list is used by the Dojo Offline Toolkit - // to cache these resources to ensure the machinery - // used by this storage provider is available offline. - // What is returned is an array of URLs. - // Note that Dojo Offline uses Gears as its native - // storage provider, and does not support using other - // kinds of storage providers while offline anymore. - - return []; - } -}); - -} - -if(!dojo._hasResource["dojox.storage.manager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojox.storage.manager"] = true; -dojo.provide("dojox.storage.manager"); -//dojo.require("dojo.AdapterRegistry"); -// FIXME: refactor this to use an AdapterRegistry - -dojox.storage.manager = new function(){ - // summary: A singleton class in charge of the dojox.storage system - // description: - // Initializes the storage systems and figures out the best available - // storage options on this platform. - - // currentProvider: Object - // The storage provider that was automagically chosen to do storage - // on this platform, such as dojox.storage.FlashStorageProvider. - this.currentProvider = null; - - // available: Boolean - // Whether storage of some kind is available. - this.available = false; - - // providers: Array - // Array of all the static provider instances, useful if you want to - // loop through and see what providers have been registered. - this.providers = []; - - this._initialized = false; - - this._onLoadListeners = []; - - this.initialize = function(){ - // summary: - // Initializes the storage system and autodetects the best storage - // provider we can provide on this platform - this.autodetect(); - }; - - this.register = function(/*string*/ name, /*Object*/ instance){ - // summary: - // Registers the existence of a new storage provider; used by - // subclasses to inform the manager of their existence. The - // storage manager will select storage providers based on - // their ordering, so the order in which you call this method - // matters. - // name: - // The full class name of this provider, such as - // "dojox.storage.FlashStorageProvider". - // instance: - // An instance of this provider, which we will use to call - // isAvailable() on. - - // keep list of providers as a list so that we can know what order - // storage providers are preferred; also, store the providers hashed - // by name in case someone wants to get a provider that uses - // a particular storage backend - this.providers.push(instance); - this.providers[name] = instance; - }; - - this.setProvider = function(storageClass){ - // summary: - // Instructs the storageManager to use the given storage class for - // all storage requests. - // description: - // Example- - // dojox.storage.setProvider( - // dojox.storage.IEStorageProvider) - - }; - - this.autodetect = function(){ - // summary: - // Autodetects the best possible persistent storage provider - // available on this platform. - - //console.debug("dojox.storage.manager.autodetect"); - - if(this._initialized){ // already finished - return; - } - - // a flag to force the storage manager to use a particular - // storage provider type, such as - // djConfig = {forceStorageProvider: "dojox.storage.WhatWGStorageProvider"}; - var forceProvider = dojo.config["forceStorageProvider"] || false; - - // go through each provider, seeing if it can be used - var providerToUse; - //FIXME: use dojo.some - for(var i = 0; i < this.providers.length; i++){ - providerToUse = this.providers[i]; - if(forceProvider && forceProvider == providerToUse.declaredClass){ - // still call isAvailable for this provider, since this helps some - // providers internally figure out if they are available - // FIXME: This should be refactored since it is non-intuitive - // that isAvailable() would initialize some state - providerToUse.isAvailable(); - break; - }else if(!forceProvider && providerToUse.isAvailable()){ - break; - } - } - - if(!providerToUse){ // no provider available - this._initialized = true; - this.available = false; - this.currentProvider = null; - console.warn("No storage provider found for this platform"); - this.loaded(); - return; - } - - // create this provider and mix in it's properties - // so that developers can do dojox.storage.put rather - // than dojox.storage.currentProvider.put, for example - this.currentProvider = providerToUse; - dojo.mixin(dojox.storage, this.currentProvider); - - // have the provider initialize itself - dojox.storage.initialize(); - - this._initialized = true; - this.available = true; - }; - - this.isAvailable = function(){ /*Boolean*/ - // summary: Returns whether any storage options are available. - return this.available; - }; - - this.addOnLoad = function(func){ /* void */ - // summary: - // Adds an onload listener to know when Dojo Offline can be used. - // description: - // Adds a listener to know when Dojo Offline can be used. This - // ensures that the Dojo Offline framework is loaded and that the - // local dojox.storage system is ready to be used. This method is - // useful if you don't want to have a dependency on Dojo Events - // when using dojox.storage. - // func: Function - // A function to call when Dojo Offline is ready to go - this._onLoadListeners.push(func); - - if(this.isInitialized()){ - this._fireLoaded(); - } - }; - - this.removeOnLoad = function(func){ /* void */ - // summary: Removes the given onLoad listener - for(var i = 0; i < this._onLoadListeners.length; i++){ - if(func == this._onLoadListeners[i]){ - this._onLoadListeners = this._onLoadListeners.splice(i, 1); - break; - } - } - }; - - this.isInitialized = function(){ /*Boolean*/ - // summary: - // Returns whether the storage system is initialized and ready to - // be used. - - // FIXME: This should REALLY not be in here, but it fixes a tricky - // Flash timing bug. - // Confirm that this is still needed with the newly refactored Dojo - // Flash. Used to be for Internet Explorer. -- Brad Neuberg - if(this.currentProvider != null - && this.currentProvider.declaredClass == "dojox.storage.FlashStorageProvider" - && dojox.flash.ready == false){ - return false; - }else{ - return this._initialized; - } - }; - - this.supportsProvider = function(/*string*/ storageClass){ /* Boolean */ - // summary: Determines if this platform supports the given storage provider. - // description: - // Example- - // dojox.storage.manager.supportsProvider( - // "dojox.storage.InternetExplorerStorageProvider"); - - // construct this class dynamically - try{ - // dynamically call the given providers class level isAvailable() - // method - var provider = eval("new " + storageClass + "()"); - var results = provider.isAvailable(); - if(!results){ return false; } - return results; - }catch(e){ - return false; - } - }; - - this.getProvider = function(){ /* Object */ - // summary: Gets the current provider - return this.currentProvider; - }; - - this.loaded = function(){ - // summary: - // The storage provider should call this method when it is loaded - // and ready to be used. Clients who will use the provider will - // connect to this method to know when they can use the storage - // system. You can either use dojo.connect to connect to this - // function, or can use dojox.storage.manager.addOnLoad() to add - // a listener that does not depend on the dojo.event package. - // description: - // Example 1- - // if(dojox.storage.manager.isInitialized() == false){ - // dojo.connect(dojox.storage.manager, "loaded", TestStorage, "initialize"); - // }else{ - // dojo.connect(dojo, "loaded", TestStorage, "initialize"); - // } - // Example 2- - // dojox.storage.manager.addOnLoad(someFunction); - - - // FIXME: we should just provide a Deferred for this. That way you - // don't care when this happens or has happened. Deferreds are in Base - this._fireLoaded(); - }; - - this._fireLoaded = function(){ - //console.debug("dojox.storage.manager._fireLoaded"); - - dojo.forEach(this._onLoadListeners, function(i){ - try{ - i(); - }catch(e){ console.debug(e); } - }); - }; - - this.getResourceList = function(){ - // summary: - // Returns a list of whatever resources are necessary for storage - // providers to work. - // description: - // This will return all files needed by all storage providers for - // this particular environment type. For example, if we are in the - // browser environment, then this will return the hidden SWF files - // needed by the FlashStorageProvider, even if we don't need them - // for the particular browser we are working within. This is meant - // to faciliate Dojo Offline, which must retrieve all resources we - // need offline into the offline cache -- we retrieve everything - // needed, in case another browser that requires different storage - // mechanisms hits the local offline cache. For example, if we - // were to sync against Dojo Offline on Firefox 2, then we would - // not grab the FlashStorageProvider resources needed for Safari. - var results = []; - dojo.forEach(dojox.storage.manager.providers, function(currentProvider){ - results = results.concat(currentProvider.getResourceList()); - }); - - return results; - } -}; - -} - -if(!dojo._hasResource["dojox._sql._crypto"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojox._sql._crypto"] = true; -// Taken from http://www.movable-type.co.uk/scripts/aes.html by -// Chris Veness (CLA signed); adapted for Dojo and Google Gears Worker Pool -// by Brad Neuberg, bkn3@columbia.edu - -dojo.provide("dojox._sql._crypto"); - -dojo.mixin(dojox._sql._crypto,{ - // _POOL_SIZE: - // Size of worker pool to create to help with crypto - _POOL_SIZE: 100, - - encrypt: function(plaintext, password, callback){ - // summary: - // Use Corrected Block TEA to encrypt plaintext using password - // (note plaintext & password must be strings not string objects). - // Results will be returned to the 'callback' asychronously. - this._initWorkerPool(); - - var msg ={plaintext: plaintext, password: password}; - msg = dojo.toJson(msg); - msg = "encr:" + String(msg); - - this._assignWork(msg, callback); - }, - - decrypt: function(ciphertext, password, callback){ - // summary: - // Use Corrected Block TEA to decrypt ciphertext using password - // (note ciphertext & password must be strings not string objects). - // Results will be returned to the 'callback' asychronously. - this._initWorkerPool(); - - var msg ={ciphertext: ciphertext, password: password}; - msg = dojo.toJson(msg); - msg = "decr:" + String(msg); - - this._assignWork(msg, callback); - }, - - _initWorkerPool: function(){ - // bugs in Google Gears prevents us from dynamically creating - // and destroying workers as we need them -- the worker - // pool functionality stops working after a number of crypto - // cycles (probably related to a memory leak in Google Gears). - // this is too bad, since it results in much simpler code. - - // instead, we have to create a pool of workers and reuse them. we - // keep a stack of 'unemployed' Worker IDs that are currently not working. - // if a work request comes in, we pop off the 'unemployed' stack - // and put them to work, storing them in an 'employed' hashtable, - // keyed by their Worker ID with the value being the callback function - // that wants the result. when an employed worker is done, we get - // a message in our 'manager' which adds this worker back to the - // unemployed stack and routes the result to the callback that - // wanted it. if all the workers were employed in the past but - // more work needed to be done (i.e. it's a tight labor pool ;) - // then the work messages are pushed onto - // a 'handleMessage' queue as an object tuple{msg: msg, callback: callback} - - if(!this._manager){ - try{ - this._manager = google.gears.factory.create("beta.workerpool", "1.0"); - this._unemployed = []; - this._employed ={}; - this._handleMessage = []; - - var self = this; - this._manager.onmessage = function(msg, sender){ - // get the callback necessary to serve this result - var callback = self._employed["_" + sender]; - - // make this worker unemployed - self._employed["_" + sender] = undefined; - self._unemployed.push("_" + sender); - - // see if we need to assign new work - // that was queued up needing to be done - if(self._handleMessage.length){ - var handleMe = self._handleMessage.shift(); - self._assignWork(handleMe.msg, handleMe.callback); - } - - // return results - callback(msg); - } - - var workerInit = "function _workerInit(){" - + "gearsWorkerPool.onmessage = " - + String(this._workerHandler) - + ";" - + "}"; - - var code = workerInit + " _workerInit();"; - - // create our worker pool - for(var i = 0; i < this._POOL_SIZE; i++){ - this._unemployed.push("_" + this._manager.createWorker(code)); - } - }catch(exp){ - throw exp.message||exp; - } - } - }, - - _assignWork: function(msg, callback){ - // can we immediately assign this work? - if(!this._handleMessage.length && this._unemployed.length){ - // get an unemployed worker - var workerID = this._unemployed.shift().substring(1); // remove _ - - // list this worker as employed - this._employed["_" + workerID] = callback; - - // do the worke - this._manager.sendMessage(msg, workerID); - }else{ - // we have to queue it up - this._handleMessage ={msg: msg, callback: callback}; - } - }, - - _workerHandler: function(msg, sender){ - - /* Begin AES Implementation */ - - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - // Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [§5.1.1] - var Sbox = [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, - 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, - 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, - 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, - 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, - 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, - 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, - 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, - 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, - 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, - 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, - 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, - 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, - 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, - 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, - 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16]; - - // Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2] - var Rcon = [ [0x00, 0x00, 0x00, 0x00], - [0x01, 0x00, 0x00, 0x00], - [0x02, 0x00, 0x00, 0x00], - [0x04, 0x00, 0x00, 0x00], - [0x08, 0x00, 0x00, 0x00], - [0x10, 0x00, 0x00, 0x00], - [0x20, 0x00, 0x00, 0x00], - [0x40, 0x00, 0x00, 0x00], - [0x80, 0x00, 0x00, 0x00], - [0x1b, 0x00, 0x00, 0x00], - [0x36, 0x00, 0x00, 0x00] ]; - - /* - * AES Cipher function: encrypt 'input' with Rijndael algorithm - * - * takes byte-array 'input' (16 bytes) - * 2D byte-array key schedule 'w' (Nr+1 x Nb bytes) - * - * applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage - * - * returns byte-array encrypted value (16 bytes) - */ - function Cipher(input, w) { // main Cipher function [§5.1] - var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES) - var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys - - var state = [[],[],[],[]]; // initialise 4xNb byte-array 'state' with input [§3.4] - for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i]; - - state = AddRoundKey(state, w, 0, Nb); - - for (var round=1; round 6 && i%Nk == 4) { - temp = SubWord(temp); - } - for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t]; - } - - return w; - } - - function SubWord(w) { // apply SBox to 4-byte word w - for (var i=0; i<4; i++) w[i] = Sbox[w[i]]; - return w; - } - - function RotWord(w) { // rotate 4-byte word w left by one byte - w[4] = w[0]; - for (var i=0; i<4; i++) w[i] = w[i+1]; - return w; - } - - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - /* - * Use AES to encrypt 'plaintext' with 'password' using 'nBits' key, in 'Counter' mode of operation - * - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - * for each block - * - outputblock = cipher(counter, key) - * - cipherblock = plaintext xor outputblock - */ - function AESEncryptCtr(plaintext, password, nBits) { - if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys - - // for this example script, generate the key by applying Cipher to 1st 16/24/32 chars of password; - // for real-world applications, a more secure approach would be to hash the password e.g. with SHA-1 - var nBytes = nBits/8; // no bytes in key - var pwBytes = new Array(nBytes); - for (var i=0; i>> i*8) & 0xff; - for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff; - - // generate key schedule - an expansion of the key into distinct Key Rounds for each round - var keySchedule = KeyExpansion(key); - - var blockCount = Math.ceil(plaintext.length/blockSize); - var ciphertext = new Array(blockCount); // ciphertext as array of strings - - for (var b=0; b>> c*8) & 0xff; - for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8) - - var cipherCntr = Cipher(counterBlock, keySchedule); // -- encrypt counter block -- - - // calculate length of final block: - var blockLength = b>> c*8) & 0xff; - for (var c=0; c<4; c++) counterBlock[15-c-4] = ((b/0x100000000-1) >>> c*8) & 0xff; - - var cipherCntr = Cipher(counterBlock, keySchedule); // encrypt counter block - - ciphertext[b] = unescCtrlChars(ciphertext[b]); - - var pt = ''; - for (var i=0; i 63){ - this.dbName = this.dbName.substring(0, 63); - } - } - - if(!dbName){ - dbName = this.dbName; - } - - try{ - this._initDb(); - this.db.open(dbName); - this._dbOpen = true; - }catch(exp){ - throw exp.message||exp; - } - }, - - close: function(dbName){ - // on Internet Explorer, Google Gears throws an exception - // "Object not a collection", when we try to close the - // database -- just don't close it on this platform - // since we are running into a Gears bug; the Gears team - // said it's ok to not close a database connection - if(dojo.isIE){ return; } - - if(!this._dbOpen && (!dbName || dbName == this.dbName)){ - return; - } - - if(!dbName){ - dbName = this.dbName; - } - - try{ - this.db.close(dbName); - this._dbOpen = false; - }catch(exp){ - throw exp.message||exp; - } - }, - - _exec: function(params){ - try{ - // get the Gears Database object - this._initDb(); - - // see if we need to open the db; if programmer - // manually called dojox.sql.open() let them handle - // it; otherwise we open and close automatically on - // each SQL execution - if(!this._dbOpen){ - this.open(); - this._autoClose = true; - } - - // determine our parameters - var sql = null; - var callback = null; - var password = null; - - var args = dojo._toArray(params); - - sql = args.splice(0, 1)[0]; - - // does this SQL statement use the ENCRYPT or DECRYPT - // keywords? if so, extract our callback and crypto - // password - if(this._needsEncrypt(sql) || this._needsDecrypt(sql)){ - callback = args.splice(args.length - 1, 1)[0]; - password = args.splice(args.length - 1, 1)[0]; - } - - // 'args' now just has the SQL parameters - - // print out debug SQL output if the developer wants that - if(this.debug){ - this._printDebugSQL(sql, args); - } - - // handle SQL that needs encryption/decryption differently - // do we have an ENCRYPT SQL statement? if so, handle that first - if(this._needsEncrypt(sql)){ - var crypto = new dojox.sql._SQLCrypto("encrypt", sql, - password, args, - callback); - return; // encrypted results will arrive asynchronously - }else if(this._needsDecrypt(sql)){ // otherwise we have a DECRYPT statement - var crypto = new dojox.sql._SQLCrypto("decrypt", sql, - password, args, - callback); - return; // decrypted results will arrive asynchronously - } - - // execute the SQL and get the results - var rs = this.db.execute(sql, args); - - // Gears ResultSet object's are ugly -- normalize - // these into something JavaScript programmers know - // how to work with, basically an array of - // JavaScript objects where each property name is - // simply the field name for a column of data - rs = this._normalizeResults(rs); - - if(this._autoClose){ - this.close(); - } - - return rs; - }catch(exp){ - exp = exp.message||exp; - - console.debug("SQL Exception: " + exp); - - if(this._autoClose){ - try{ - this.close(); - }catch(e){ - console.debug("Error closing database: " - + e.message||e); - } - } - - throw exp; - } - }, - - _initDb: function(){ - if(!this.db){ - try{ - this.db = google.gears.factory.create('beta.database', '1.0'); - }catch(exp){ - dojo.setObject("google.gears.denied", true); - dojox.off.onFrameworkEvent("coreOperationFailed"); - throw "Google Gears must be allowed to run"; - } - } - }, - - _printDebugSQL: function(sql, args){ - var msg = "dojox.sql(\"" + sql + "\""; - for(var i = 0; i < args.length; i++){ - if(typeof args[i] == "string"){ - msg += ", \"" + args[i] + "\""; - }else{ - msg += ", " + args[i]; - } - } - msg += ")"; - - console.debug(msg); - }, - - _normalizeResults: function(rs){ - var results = []; - if(!rs){ return []; } - - while(rs.isValidRow()){ - var row = {}; - - for(var i = 0; i < rs.fieldCount(); i++){ - var fieldName = rs.fieldName(i); - var fieldValue = rs.field(i); - row[fieldName] = fieldValue; - } - - results.push(row); - - rs.next(); - } - - rs.close(); - - return results; - }, - - _needsEncrypt: function(sql){ - return /encrypt\([^\)]*\)/i.test(sql); - }, - - _needsDecrypt: function(sql){ - return /decrypt\([^\)]*\)/i.test(sql); - } -}); - -// summary: -// A private class encapsulating any cryptography that must be done -// on a SQL statement. We instantiate this class and have it hold -// it's state so that we can potentially have several encryption -// operations happening at the same time by different SQL statements. -dojo.declare("dojox.sql._SQLCrypto", null, { - constructor: function(action, sql, password, args, callback){ - if(action == "encrypt"){ - this._execEncryptSQL(sql, password, args, callback); - }else{ - this._execDecryptSQL(sql, password, args, callback); - } - }, - - _execEncryptSQL: function(sql, password, args, callback){ - // strip the ENCRYPT/DECRYPT keywords from the SQL - var strippedSQL = this._stripCryptoSQL(sql); - - // determine what arguments need encryption - var encryptColumns = this._flagEncryptedArgs(sql, args); - - // asynchronously encrypt each argument that needs it - var self = this; - this._encrypt(strippedSQL, password, args, encryptColumns, function(finalArgs){ - // execute the SQL - var error = false; - var resultSet = []; - var exp = null; - try{ - resultSet = dojox.sql.db.execute(strippedSQL, finalArgs); - }catch(execError){ - error = true; - exp = execError.message||execError; - } - - // was there an error during SQL execution? - if(exp != null){ - if(dojox.sql._autoClose){ - try{ dojox.sql.close(); }catch(e){} - } - - callback(null, true, exp.toString()); - return; - } - - // normalize SQL results into a JavaScript object - // we can work with - resultSet = dojox.sql._normalizeResults(resultSet); - - if(dojox.sql._autoClose){ - dojox.sql.close(); - } - - // are any decryptions necessary on the result set? - if(dojox.sql._needsDecrypt(sql)){ - // determine which of the result set columns needs decryption - var needsDecrypt = self._determineDecryptedColumns(sql); - - // now decrypt columns asynchronously - // decrypt columns that need it - self._decrypt(resultSet, needsDecrypt, password, function(finalResultSet){ - callback(finalResultSet, false, null); - }); - }else{ - callback(resultSet, false, null); - } - }); - }, - - _execDecryptSQL: function(sql, password, args, callback){ - // strip the ENCRYPT/DECRYPT keywords from the SQL - var strippedSQL = this._stripCryptoSQL(sql); - - // determine which columns needs decryption; this either - // returns the value *, which means all result set columns will - // be decrypted, or it will return the column names that need - // decryption set on a hashtable so we can quickly test a given - // column name; the key is the column name that needs - // decryption and the value is 'true' (i.e. needsDecrypt["someColumn"] - // would return 'true' if it needs decryption, and would be 'undefined' - // or false otherwise) - var needsDecrypt = this._determineDecryptedColumns(sql); - - // execute the SQL - var error = false; - var resultSet = []; - var exp = null; - try{ - resultSet = dojox.sql.db.execute(strippedSQL, args); - }catch(execError){ - error = true; - exp = execError.message||execError; - } - - // was there an error during SQL execution? - if(exp != null){ - if(dojox.sql._autoClose){ - try{ dojox.sql.close(); }catch(e){} - } - - callback(resultSet, true, exp.toString()); - return; - } - - // normalize SQL results into a JavaScript object - // we can work with - resultSet = dojox.sql._normalizeResults(resultSet); - - if(dojox.sql._autoClose){ - dojox.sql.close(); - } - - // decrypt columns that need it - this._decrypt(resultSet, needsDecrypt, password, function(finalResultSet){ - callback(finalResultSet, false, null); - }); - }, - - _encrypt: function(sql, password, args, encryptColumns, callback){ - //console.debug("_encrypt, sql="+sql+", password="+password+", encryptColumns="+encryptColumns+", args="+args); - - this._totalCrypto = 0; - this._finishedCrypto = 0; - this._finishedSpawningCrypto = false; - this._finalArgs = args; - - for(var i = 0; i < args.length; i++){ - if(encryptColumns[i]){ - // we have an encrypt() keyword -- get just the value inside - // the encrypt() parantheses -- for now this must be a ? - var sqlParam = args[i]; - var paramIndex = i; - - // update the total number of encryptions we know must be done asynchronously - this._totalCrypto++; - - // FIXME: This currently uses DES as a proof-of-concept since the - // DES code used is quite fast and was easy to work with. Modify dojox.sql - // to be able to specify a different encryption provider through a - // a SQL-like syntax, such as dojox.sql("SET ENCRYPTION BLOWFISH"), - // and modify the dojox.crypto.Blowfish code to be able to work using - // a Google Gears Worker Pool - - // do the actual encryption now, asychronously on a Gears worker thread - dojox._sql._crypto.encrypt(sqlParam, password, dojo.hitch(this, function(results){ - // set the new encrypted value - this._finalArgs[paramIndex] = results; - this._finishedCrypto++; - // are we done with all encryption? - if(this._finishedCrypto >= this._totalCrypto - && this._finishedSpawningCrypto){ - callback(this._finalArgs); - } - })); - } - } - - this._finishedSpawningCrypto = true; - }, - - _decrypt: function(resultSet, needsDecrypt, password, callback){ - //console.debug("decrypt, resultSet="+resultSet+", needsDecrypt="+needsDecrypt+", password="+password); - - this._totalCrypto = 0; - this._finishedCrypto = 0; - this._finishedSpawningCrypto = false; - this._finalResultSet = resultSet; - - for(var i = 0; i < resultSet.length; i++){ - var row = resultSet[i]; - - // go through each of the column names in row, - // seeing if they need decryption - for(var columnName in row){ - if(needsDecrypt == "*" || needsDecrypt[columnName]){ - this._totalCrypto++; - var columnValue = row[columnName]; - - // forming a closure here can cause issues, with values not cleanly - // saved on Firefox/Mac OS X for some of the values above that - // are needed in the callback below; call a subroutine that will form - // a closure inside of itself instead - this._decryptSingleColumn(columnName, columnValue, password, i, - function(finalResultSet){ - callback(finalResultSet); - }); - } - } - } - - this._finishedSpawningCrypto = true; - }, - - _stripCryptoSQL: function(sql){ - // replace all DECRYPT(*) occurrences with a * - sql = sql.replace(/DECRYPT\(\*\)/ig, "*"); - - // match any ENCRYPT(?, ?, ?, etc) occurrences, - // then replace with just the question marks in the - // middle - var matches = sql.match(/ENCRYPT\([^\)]*\)/ig); - if(matches != null){ - for(var i = 0; i < matches.length; i++){ - var encryptStatement = matches[i]; - var encryptValue = encryptStatement.match(/ENCRYPT\(([^\)]*)\)/i)[1]; - sql = sql.replace(encryptStatement, encryptValue); - } - } - - // match any DECRYPT(COL1, COL2, etc) occurrences, - // then replace with just the column names - // in the middle - matches = sql.match(/DECRYPT\([^\)]*\)/ig); - if(matches != null){ - for(var i = 0; i < matches.length; i++){ - var decryptStatement = matches[i]; - var decryptValue = decryptStatement.match(/DECRYPT\(([^\)]*)\)/i)[1]; - sql = sql.replace(decryptStatement, decryptValue); - } - } - - return sql; - }, - - _flagEncryptedArgs: function(sql, args){ - // capture literal strings that have question marks in them, - // and also capture question marks that stand alone - var tester = new RegExp(/([\"][^\"]*\?[^\"]*[\"])|([\'][^\']*\?[^\']*[\'])|(\?)/ig); - var matches; - var currentParam = 0; - var results = []; - while((matches = tester.exec(sql)) != null){ - var currentMatch = RegExp.lastMatch+""; - - // are we a literal string? then ignore it - if(/^[\"\']/.test(currentMatch)){ - continue; - } - - // do we have an encrypt keyword to our left? - var needsEncrypt = false; - if(/ENCRYPT\([^\)]*$/i.test(RegExp.leftContext)){ - needsEncrypt = true; - } - - // set the encrypted flag - results[currentParam] = needsEncrypt; - - currentParam++; - } - - return results; - }, - - _determineDecryptedColumns: function(sql){ - var results = {}; - - if(/DECRYPT\(\*\)/i.test(sql)){ - results = "*"; - }else{ - var tester = /DECRYPT\((?:\s*\w*\s*\,?)*\)/ig; - var matches; - while(matches = tester.exec(sql)){ - var lastMatch = new String(RegExp.lastMatch); - var columnNames = lastMatch.replace(/DECRYPT\(/i, ""); - columnNames = columnNames.replace(/\)/, ""); - columnNames = columnNames.split(/\s*,\s*/); - dojo.forEach(columnNames, function(column){ - if(/\s*\w* AS (\w*)/i.test(column)){ - column = column.match(/\s*\w* AS (\w*)/i)[1]; - } - results[column] = true; - }); - } - } - - return results; - }, - - _decryptSingleColumn: function(columnName, columnValue, password, currentRowIndex, - callback){ - //console.debug("decryptSingleColumn, columnName="+columnName+", columnValue="+columnValue+", currentRowIndex="+currentRowIndex) - dojox._sql._crypto.decrypt(columnValue, password, dojo.hitch(this, function(results){ - // set the new decrypted value - this._finalResultSet[currentRowIndex][columnName] = results; - this._finishedCrypto++; - - // are we done with all encryption? - if(this._finishedCrypto >= this._totalCrypto - && this._finishedSpawningCrypto){ - //console.debug("done with all decrypts"); - callback(this._finalResultSet); - } - })); - } -}); - -} - -if(!dojo._hasResource["dojox.sql"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojox.sql"] = true; - -dojo.provide("dojox.sql"); - -} - -if(!dojo._hasResource["dojox.storage.GearsStorageProvider"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojox.storage.GearsStorageProvider"] = true; -dojo.provide("dojox.storage.GearsStorageProvider"); - - - - -if(dojo.isGears){ - - (function(){ - // make sure we don't define the gears provider if we're not gears - // enabled - - dojo.declare("dojox.storage.GearsStorageProvider", dojox.storage.Provider, { - // summary: - // Storage provider that uses the features of Google Gears - // to store data (it is saved into the local SQL database - // provided by Gears, using dojox.sql) - // description: - // You can disable this storage provider with the following djConfig - // variable: - // var djConfig = { disableGearsStorage: true }; - // - // Authors of this storage provider- - // Brad Neuberg, bkn3@columbia.edu - constructor: function(){ - }, - // instance methods and properties - TABLE_NAME: "__DOJO_STORAGE", - initialized: false, - - _available: null, - - initialize: function(){ - //console.debug("dojox.storage.GearsStorageProvider.initialize"); - if(dojo.config["disableGearsStorage"] == true){ - return; - } - - // partition our storage data so that multiple apps - // on the same host won't collide - this.TABLE_NAME = "__DOJO_STORAGE"; - - // create the table that holds our data - try{ - dojox.sql("CREATE TABLE IF NOT EXISTS " + this.TABLE_NAME + "( " - + " namespace TEXT, " - + " key TEXT, " - + " value TEXT " - + ")" - ); - dojox.sql("CREATE UNIQUE INDEX IF NOT EXISTS namespace_key_index" - + " ON " + this.TABLE_NAME - + " (namespace, key)"); - }catch(e){ - console.debug("dojox.storage.GearsStorageProvider.initialize:", e); - - this.initialized = false; // we were unable to initialize - dojox.storage.manager.loaded(); - return; - } - - // indicate that this storage provider is now loaded - this.initialized = true; - dojox.storage.manager.loaded(); - }, - - isAvailable: function(){ - // is Google Gears available and defined? - return this._available = dojo.isGears; - }, - - put: function(key, value, resultsHandler, namespace){ - if(this.isValidKey(key) == false){ - throw new Error("Invalid key given: " + key); - } - namespace = namespace||this.DEFAULT_NAMESPACE; - - // serialize the value; - // handle strings differently so they have better performance - if(dojo.isString(value)){ - value = "string:" + value; - }else{ - value = dojo.toJson(value); - } - - // try to store the value - try{ - dojox.sql("DELETE FROM " + this.TABLE_NAME - + " WHERE namespace = ? AND key = ?", - namespace, key); - dojox.sql("INSERT INTO " + this.TABLE_NAME - + " VALUES (?, ?, ?)", - namespace, key, value); - }catch(e){ - // indicate we failed - console.debug("dojox.storage.GearsStorageProvider.put:", e); - resultsHandler(this.FAILED, key, e.toString()); - return; - } - - if(resultsHandler){ - resultsHandler(dojox.storage.SUCCESS, key, null); - } - }, - - get: function(key, namespace){ - if(this.isValidKey(key) == false){ - throw new Error("Invalid key given: " + key); - } - namespace = namespace||this.DEFAULT_NAMESPACE; - - // try to find this key in the database - var results = dojox.sql("SELECT * FROM " + this.TABLE_NAME - + " WHERE namespace = ? AND " - + " key = ?", - namespace, key); - if(!results.length){ - return null; - }else{ - results = results[0].value; - } - - // destringify the content back into a - // real JavaScript object; - // handle strings differently so they have better performance - if(dojo.isString(results) && (/^string:/.test(results))){ - results = results.substring("string:".length); - }else{ - results = dojo.fromJson(results); - } - - return results; - }, - - getNamespaces: function(){ - var results = [ dojox.storage.DEFAULT_NAMESPACE ]; - - var rs = dojox.sql("SELECT namespace FROM " + this.TABLE_NAME - + " DESC GROUP BY namespace"); - for(var i = 0; i < rs.length; i++){ - if(rs[i].namespace != dojox.storage.DEFAULT_NAMESPACE){ - results.push(rs[i].namespace); - } - } - - return results; - }, - - getKeys: function(namespace){ - namespace = namespace||this.DEFAULT_NAMESPACE; - if(this.isValidKey(namespace) == false){ - throw new Error("Invalid namespace given: " + namespace); - } - - var rs = dojox.sql("SELECT key FROM " + this.TABLE_NAME - + " WHERE namespace = ?", - namespace); - - var results = []; - for(var i = 0; i < rs.length; i++){ - results.push(rs[i].key); - } - - return results; - }, - - clear: function(namespace){ - if(this.isValidKey(namespace) == false){ - throw new Error("Invalid namespace given: " + namespace); - } - namespace = namespace||this.DEFAULT_NAMESPACE; - - dojox.sql("DELETE FROM " + this.TABLE_NAME - + " WHERE namespace = ?", - namespace); - }, - - remove: function(key, namespace){ - namespace = namespace||this.DEFAULT_NAMESPACE; - - dojox.sql("DELETE FROM " + this.TABLE_NAME - + " WHERE namespace = ? AND" - + " key = ?", - namespace, - key); - }, - - putMultiple: function(keys, values, resultsHandler, namespace) { - if(this.isValidKeyArray(keys) === false - || ! values instanceof Array - || keys.length != values.length){ - throw new Error("Invalid arguments: keys = [" - + keys + "], values = [" + values + "]"); - } - - if(namespace == null || typeof namespace == "undefined"){ - namespace = dojox.storage.DEFAULT_NAMESPACE; - } - - if(this.isValidKey(namespace) == false){ - throw new Error("Invalid namespace given: " + namespace); - } - - this._statusHandler = resultsHandler; - - // try to store the value - try{ - dojox.sql.open(); - dojox.sql.db.execute("BEGIN TRANSACTION"); - var _stmt = "REPLACE INTO " + this.TABLE_NAME + " VALUES (?, ?, ?)"; - for(var i=0;i dew){ - minw = dew; - maxw = dbw; - }else{ - maxw = dew; - minw = dbw; - } - var dbh = _document.body.clientHeight; - if(dbh > deh){ - minh = deh; - maxh = dbh; - }else{ - maxh = deh; - minh = dbh; - } - w = (maxw > _window.innerWidth) ? minw : maxw; - h = (maxh > _window.innerHeight) ? minh : maxh; - }else if(!dojo.isOpera && _window.innerWidth){ - //in opera9, dojo.body().clientWidth should be used, instead - //of window.innerWidth/document.documentElement.clientWidth - //so we have to check whether it is opera - w = _window.innerWidth; - h = _window.innerHeight; - }else if(dojo.isIE && de && deh){ - w = dew; - h = deh; - }else if(dojo.body().clientWidth){ - // IE5, Opera - w = dojo.body().clientWidth; - h = dojo.body().clientHeight; - } - - // get scroll position - var scroll = dojo._docScroll(); - - return { w: w, h: h, l: scroll.x, t: scroll.y }; // object -}; - -dijit.placeOnScreen = function( - /* DomNode */ node, - /* Object */ pos, - /* Object */ corners, - /* boolean? */ tryOnly){ - // summary: - // Keeps 'node' in the visible area of the screen while trying to - // place closest to pos.x, pos.y. The input coordinates are - // expected to be the desired document position. - // - // Set which corner(s) you want to bind to, such as - // - // placeOnScreen(node, {x: 10, y: 20}, ["TR", "BL"]) - // - // The desired x/y will be treated as the topleft(TL)/topright(TR) or - // BottomLeft(BL)/BottomRight(BR) corner of the node. Each corner is tested - // and if a perfect match is found, it will be used. Otherwise, it goes through - // all of the specified corners, and choose the most appropriate one. - // - // NOTE: node is assumed to be absolutely or relatively positioned. - - var choices = dojo.map(corners, function(corner){ return { corner: corner, pos: pos }; }); - - return dijit._place(node, choices); -} - -dijit._place = function(/*DomNode*/ node, /* Array */ choices, /* Function */ layoutNode){ - // summary: - // Given a list of spots to put node, put it at the first spot where it fits, - // of if it doesn't fit anywhere then the place with the least overflow - // choices: Array - // Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} } - // Above example says to put the top-left corner of the node at (10,20) - // layoutNode: Function(node, aroundNodeCorner, nodeCorner) - // for things like tooltip, they are displayed differently (and have different dimensions) - // based on their orientation relative to the parent. This adjusts the popup based on orientation. - - // get {x: 10, y: 10, w: 100, h:100} type obj representing position of - // viewport over document - var view = dijit.getViewport(); - - // This won't work if the node is inside a
, - // so reattach it to dojo.doc.body. (Otherwise, the positioning will be wrong - // and also it might get cutoff) - if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){ - dojo.body().appendChild(node); - } - - var best = null; - dojo.some(choices, function(choice){ - var corner = choice.corner; - var pos = choice.pos; - - // configure node to be displayed in given position relative to button - // (need to do this in order to get an accurate size for the node, because - // a tooltips size changes based on position, due to triangle) - if(layoutNode){ - layoutNode(node, choice.aroundCorner, corner); - } - - // get node's size - var style = node.style; - var oldDisplay = style.display; - var oldVis = style.visibility; - style.visibility = "hidden"; - style.display = ""; - var mb = dojo.marginBox(node); - style.display = oldDisplay; - style.visibility = oldVis; - - // coordinates and size of node with specified corner placed at pos, - // and clipped by viewport - var startX = (corner.charAt(1) == 'L' ? pos.x : Math.max(view.l, pos.x - mb.w)), - startY = (corner.charAt(0) == 'T' ? pos.y : Math.max(view.t, pos.y - mb.h)), - endX = (corner.charAt(1) == 'L' ? Math.min(view.l + view.w, startX + mb.w) : pos.x), - endY = (corner.charAt(0) == 'T' ? Math.min(view.t + view.h, startY + mb.h) : pos.y), - width = endX - startX, - height = endY - startY, - overflow = (mb.w - width) + (mb.h - height); - - if(best == null || overflow < best.overflow){ - best = { - corner: corner, - aroundCorner: choice.aroundCorner, - x: startX, - y: startY, - w: width, - h: height, - overflow: overflow - }; - } - return !overflow; - }); - - node.style.left = best.x + "px"; - node.style.top = best.y + "px"; - if(best.overflow && layoutNode){ - layoutNode(node, best.aroundCorner, best.corner); - } - return best; -} - -dijit.placeOnScreenAroundElement = function( - /* DomNode */ node, - /* DomNode */ aroundNode, - /* Object */ aroundCorners, - /* Function */ layoutNode){ - - // summary - // Like placeOnScreen, except it accepts aroundNode instead of x,y - // and attempts to place node around it. Uses margin box dimensions. - // - // aroundCorners - // specify Which corner of aroundNode should be - // used to place the node => which corner(s) of node to use (see the - // corners parameter in dijit.placeOnScreen) - // e.g. {'TL': 'BL', 'BL': 'TL'} - // - // layoutNode: Function(node, aroundNodeCorner, nodeCorner) - // for things like tooltip, they are displayed differently (and have different dimensions) - // based on their orientation relative to the parent. This adjusts the popup based on orientation. - - - // get coordinates of aroundNode - aroundNode = dojo.byId(aroundNode); - var oldDisplay = aroundNode.style.display; - aroundNode.style.display=""; - // #3172: use the slightly tighter border box instead of marginBox - var aroundNodeW = aroundNode.offsetWidth; //mb.w; - var aroundNodeH = aroundNode.offsetHeight; //mb.h; - var aroundNodePos = dojo.coords(aroundNode, true); - aroundNode.style.display=oldDisplay; - - // Generate list of possible positions for node - var choices = []; - for(var nodeCorner in aroundCorners){ - choices.push( { - aroundCorner: nodeCorner, - corner: aroundCorners[nodeCorner], - pos: { - x: aroundNodePos.x + (nodeCorner.charAt(1) == 'L' ? 0 : aroundNodeW), - y: aroundNodePos.y + (nodeCorner.charAt(0) == 'T' ? 0 : aroundNodeH) - } - }); - } - - return dijit._place(node, choices, layoutNode); -} - -} - -if(!dojo._hasResource["dojox.flash._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojox.flash._base"] = true; -dojo.provide("dojox.flash._base"); - -// for dijit.getViewport(), needed by dojox.flash.Embed.center() - - -dojox.flash = function(){ - // summary: - // The goal of dojox.flash is to make it easy to extend Flash's capabilities - // into an Ajax/DHTML environment. - // - // dojox.flash provides an easy object for interacting with the Flash plugin. - // This object provides methods to determine the current version of the Flash - // plugin (dojox.flash.info); write out the necessary markup to - // dynamically insert a Flash object into the page (dojox.flash.Embed; and - // do dynamic installation and upgrading of the current Flash plugin in - // use (dojox.flash.Install). If you want to call methods on the Flash object - // embedded into the page it is your responsibility to use Flash's ExternalInterface - // API and get a reference to the Flash object yourself. - // - // To use dojox.flash, you must first wait until Flash is finished loading - // and initializing before you attempt communication or interaction. - // To know when Flash is finished use dojo.connect: - // - // dojo.connect(dojox.flash, "loaded", myInstance, "myCallback"); - // - // Then, while the page is still loading provide the file name: - // - // dojox.flash.setSwf(dojo.moduleUrl("dojox", "_storage/storage.swf")); - // - // If no SWF files are specified, then Flash is not initialized. - // - // Your Flash must use Flash's ExternalInterface to expose Flash methods and - // to call JavaScript. - // - // setSwf can take an optional 'visible' attribute to control whether - // the Flash object is visible or not on the page; the default is visible: - // - // dojox.flash.setSwf(dojo.moduleUrl("dojox", "_storage/storage.swf"), - // false); - // - // Once finished, you can query Flash version information: - // - // dojox.flash.info.version - // - // Or can communicate with Flash methods that were exposed: - // - // var f = dojox.flash.get(); - // var results = f.sayHello("Some Message"); - // - // Your Flash files should use DojoExternalInterface.as to register methods; - // this file wraps Flash's normal ExternalInterface but correct various - // serialization bugs that ExternalInterface has. - // - // Note that dojox.flash is not meant to be a generic Flash embedding - // mechanism; it is as generic as necessary to make Dojo Storage's - // Flash Storage Provider as clean and modular as possible. If you want - // a generic Flash embed mechanism see SWFObject - // (http://blog.deconcept.com/swfobject/). - // - // Notes: - // Note that dojox.flash can currently only work with one Flash object - // on the page; it does not yet support multiple Flash objects on - // the same page. - // - // Your code can detect whether the Flash player is installing or having - // its version revved in two ways. First, if dojox.flash detects that - // Flash installation needs to occur, it sets dojox.flash.info.installing - // to true. Second, you can detect if installation is necessary with the - // following callback: - // - // dojo.connect(dojox.flash, "installing", myInstance, "myCallback"); - // - // You can use this callback to delay further actions that might need Flash; - // when installation is finished the full page will be refreshed and the - // user will be placed back on your page with Flash installed. - // - // ------------------- - // Todo/Known Issues - // ------------------- - // * On Internet Explorer, after doing a basic install, the page is - // not refreshed or does not detect that Flash is now available. The way - // to fix this is to create a custom small Flash file that is pointed to - // during installation; when it is finished loading, it does a callback - // that says that Flash installation is complete on IE, and we can proceed - // to initialize the dojox.flash subsystem. - // * Things aren't super tested for sending complex objects to Flash - // methods, since Dojo Storage only needs strings - // - // Author- Brad Neuberg, http://codinginparadise.org -} - -dojox.flash = { - ready: false, - url: null, - - _visible: true, - _loadedListeners: new Array(), - _installingListeners: new Array(), - - setSwf: function(/* String */ url, /* boolean? */ visible){ - // summary: Sets the SWF files and versions we are using. - // url: String - // The URL to this Flash file. - // visible: boolean? - // Whether the Flash file is visible or not. If it is not visible we hide it off the - // screen. This defaults to true (i.e. the Flash file is visible). - this.url = url; - - if(typeof visible != "undefined"){ - this._visible = visible; - } - - // initialize ourselves - this._initialize(); - }, - - addLoadedListener: function(/* Function */ listener){ - // summary: - // Adds a listener to know when Flash is finished loading. - // Useful if you don't want a dependency on dojo.event. - // listener: Function - // A function that will be called when Flash is done loading. - - this._loadedListeners.push(listener); - }, - - addInstallingListener: function(/* Function */ listener){ - // summary: - // Adds a listener to know if Flash is being installed. - // Useful if you don't want a dependency on dojo.event. - // listener: Function - // A function that will be called if Flash is being - // installed - - this._installingListeners.push(listener); - }, - - loaded: function(){ - // summary: Called back when the Flash subsystem is finished loading. - // description: - // A callback when the Flash subsystem is finished loading and can be - // worked with. To be notified when Flash is finished loading, add a - // loaded listener: - // - // dojox.flash.addLoadedListener(loadedListener); - - dojox.flash.ready = true; - if(dojox.flash._loadedListeners.length > 0){ - for(var i = 0;i < dojox.flash._loadedListeners.length; i++){ - dojox.flash._loadedListeners[i].call(null); - } - } - }, - - installing: function(){ - // summary: Called if Flash is being installed. - // description: - // A callback to know if Flash is currently being installed or - // having its version revved. To be notified if Flash is installing, connect - // your callback to this method using the following: - // - // dojo.event.connect(dojox.flash, "installing", myInstance, "myCallback"); - - if(dojox.flash._installingListeners.length > 0){ - for(var i = 0; i < dojox.flash._installingListeners.length; i++){ - dojox.flash._installingListeners[i].call(null); - } - } - }, - - // Initializes dojox.flash. - _initialize: function(){ - //console.debug("dojox.flash._initialize"); - // see if we need to rev or install Flash on this platform - var installer = new dojox.flash.Install(); - dojox.flash.installer = installer; - - if(installer.needed() == true){ - installer.install(); - }else{ - // write the flash object into the page - dojox.flash.obj = new dojox.flash.Embed(this._visible); - dojox.flash.obj.write(); - - // setup the communicator - dojox.flash.comm = new dojox.flash.Communicator(); - } - } -}; - - -dojox.flash.Info = function(){ - // summary: A class that helps us determine whether Flash is available. - // description: - // A class that helps us determine whether Flash is available, - // it's major and minor versions, and what Flash version features should - // be used for Flash/JavaScript communication. Parts of this code - // are adapted from the automatic Flash plugin detection code autogenerated - // by the Macromedia Flash 8 authoring environment. - // - // An instance of this class can be accessed on dojox.flash.info after - // the page is finished loading. - // - // This constructor must be called before the page is finished loading. - - // Visual basic helper required to detect Flash Player ActiveX control - // version information on Internet Explorer - if(dojo.isIE){ - document.write([ - ' - // - // Note that inline styles on elements are not handled (i.e. - // if you somehow have an inline style that uses a URL); - // object and embed tags are not scanned since their format - // differs based on type; and elements created by JavaScript - // after page load are not found. For these you must manually - // add them with a dojox.off.files.cache() method call. - - // just schedule the slurp once the page is loaded and - // Dojo Offline is ready to slurp; dojox.off will call - // our _slurp() method before indicating it is finished - // loading - this._doSlurp = true; - }, - - cache: function(urlOrList){ /* void */ - // summary: - // Caches a file or list of files to be available offline. This - // can either be a full URL, such as http://foobar.com/index.html, - // or a relative URL, such as ../index.html. This URL is not - // actually cached until dojox.off.sync.synchronize() is called. - // urlOrList: String or Array[] - // A URL of a file to cache or an Array of Strings of files to - // cache - - //console.debug("dojox.off.files.cache, urlOrList="+urlOrList); - - if(dojo.isString(urlOrList)){ - var url = this._trimAnchor(urlOrList+""); - if(!this.isAvailable(url)){ - this.listOfURLs.push(url); - } - }else if(urlOrList instanceof dojo._Url){ - var url = this._trimAnchor(urlOrList.uri); - if(!this.isAvailable(url)){ - this.listOfURLs.push(url); - } - }else{ - dojo.forEach(urlOrList, function(url){ - url = this._trimAnchor(url); - if(!this.isAvailable(url)){ - this.listOfURLs.push(url); - } - }, this); - } - }, - - printURLs: function(){ - // summary: - // A helper function that will dump and print out - // all of the URLs that are cached for offline - // availability. This can help with debugging if you - // are trying to make sure that all of your URLs are - // available offline - console.debug("The following URLs are cached for offline use:"); - dojo.forEach(this.listOfURLs, function(i){ - console.debug(i); - }); - }, - - remove: function(url){ /* void */ - // summary: - // Removes a URL from the list of files to cache. - // description: - // Removes a URL from the list of URLs to cache. Note that this - // does not actually remove the file from the offline cache; - // instead, it just prevents us from refreshing this file at a - // later time, so that it will naturally time out and be removed - // from the offline cache - // url: String - // The URL to remove - for(var i = 0; i < this.listOfURLs.length; i++){ - if(this.listOfURLs[i] == url){ - this.listOfURLs = this.listOfURLs.splice(i, 1); - break; - } - } - }, - - isAvailable: function(url){ /* boolean */ - // summary: - // Determines whether the given resource is available offline. - // url: String - // The URL to check - for(var i = 0; i < this.listOfURLs.length; i++){ - if(this.listOfURLs[i] == url){ - return true; - } - } - - return false; - }, - - refresh: function(callback){ /* void */ - //console.debug("dojox.off.files.refresh"); - // summary: - // For advanced usage; most developers can ignore this. - // Refreshes our list of offline resources, - // making them available offline. - // callback: Function - // A callback that receives two arguments: whether an error - // occurred, which is a boolean; and an array of error message strings - // with details on errors encountered. If no error occured then message is - // empty array with length 0. - try{ - if(dojo.config.isDebug){ - this.printURLs(); - } - - this.refreshing = true; - - if(this.versionURL){ - this._getVersionInfo(function(oldVersion, newVersion, justDebugged){ - //console.warn("getVersionInfo, oldVersion="+oldVersion+", newVersion="+newVersion - // + ", justDebugged="+justDebugged+", isDebug="+dojo.config.isDebug); - if(dojo.config.isDebug || !newVersion || justDebugged - || !oldVersion || oldVersion != newVersion){ - console.warn("Refreshing offline file list"); - this._doRefresh(callback, newVersion); - }else{ - console.warn("No need to refresh offline file list"); - callback(false, []); - } - }); - }else{ - console.warn("Refreshing offline file list"); - this._doRefresh(callback); - } - }catch(e){ - this.refreshing = false; - - // can't refresh files -- core operation -- - // fail fast - dojox.off.coreOpFailed = true; - dojox.off.enabled = false; - dojox.off.onFrameworkEvent("coreOperationFailed"); - } - }, - - abortRefresh: function(){ - // summary: - // For advanced usage; most developers can ignore this. - // Aborts and cancels a refresh. - if(!this.refreshing){ - return; - } - - this._store.abortCapture(this._cancelID); - this.refreshing = false; - }, - - _slurp: function(){ - if(!this._doSlurp){ - return; - } - - var handleUrl = dojo.hitch(this, function(url){ - if(this._sameLocation(url)){ - this.cache(url); - } - }); - - handleUrl(window.location.href); - - dojo.query("script").forEach(function(i){ - try{ - handleUrl(i.getAttribute("src")); - }catch(exp){ - //console.debug("dojox.off.files.slurp 'script' error: " - // + exp.message||exp); - } - }); - - dojo.query("link").forEach(function(i){ - try{ - if(!i.getAttribute("rel") - || i.getAttribute("rel").toLowerCase() != "stylesheet"){ - return; - } - - handleUrl(i.getAttribute("href")); - }catch(exp){ - //console.debug("dojox.off.files.slurp 'link' error: " - // + exp.message||exp); - } - }); - - dojo.query("img").forEach(function(i){ - try{ - handleUrl(i.getAttribute("src")); - }catch(exp){ - //console.debug("dojox.off.files.slurp 'img' error: " - // + exp.message||exp); - } - }); - - dojo.query("a").forEach(function(i){ - try{ - handleUrl(i.getAttribute("href")); - }catch(exp){ - //console.debug("dojox.off.files.slurp 'a' error: " - // + exp.message||exp); - } - }); - - // FIXME: handle 'object' and 'embed' tag - - // parse our style sheets for inline URLs and imports - dojo.forEach(document.styleSheets, function(sheet){ - try{ - if(sheet.cssRules){ // Firefox - dojo.forEach(sheet.cssRules, function(rule){ - var text = rule.cssText; - if(text){ - var matches = text.match(/url\(\s*([^\) ]*)\s*\)/i); - if(!matches){ - return; - } - - for(var i = 1; i < matches.length; i++){ - handleUrl(matches[i]) - } - } - }); - }else if(sheet.cssText){ // IE - var matches; - var text = sheet.cssText.toString(); - // unfortunately, using RegExp.exec seems to be flakey - // for looping across multiple lines on IE using the - // global flag, so we have to simulate it - var lines = text.split(/\f|\r|\n/); - for(var i = 0; i < lines.length; i++){ - matches = lines[i].match(/url\(\s*([^\) ]*)\s*\)/i); - if(matches && matches.length){ - handleUrl(matches[1]); - } - } - } - }catch(exp){ - //console.debug("dojox.off.files.slurp stylesheet parse error: " - // + exp.message||exp); - } - }); - - //this.printURLs(); - }, - - _sameLocation: function(url){ - if(!url){ return false; } - - // filter out anchors - if(url.length && url.charAt(0) == "#"){ - return false; - } - - // FIXME: dojo._Url should be made public; - // it's functionality is very useful for - // parsing URLs correctly, which is hard to - // do right - url = new dojo._Url(url); - - // totally relative -- ../../someFile.html - if(!url.scheme && !url.port && !url.host){ - return true; - } - - // scheme relative with port specified -- brad.com:8080 - if(!url.scheme && url.host && url.port - && window.location.hostname == url.host - && window.location.port == url.port){ - return true; - } - - // scheme relative with no-port specified -- brad.com - if(!url.scheme && url.host && !url.port - && window.location.hostname == url.host - && window.location.port == 80){ - return true; - } - - // else we have everything - return window.location.protocol == (url.scheme + ":") - && window.location.hostname == url.host - && (window.location.port == url.port || !window.location.port && !url.port); - }, - - _trimAnchor: function(url){ - return url.replace(/\#.*$/, ""); - }, - - _doRefresh: function(callback, newVersion){ - // get our local server - var localServer; - try{ - localServer = google.gears.factory.create("beta.localserver", "1.0"); - }catch(exp){ - dojo.setObject("google.gears.denied", true); - dojox.off.onFrameworkEvent("coreOperationFailed"); - throw "Google Gears must be allowed to run"; - } - - var storeName = "dot_store_" - + window.location.href.replace(/[^0-9A-Za-z_]/g, "_"); - - // clip at 64 characters, the max length of a resource store name - if(storeName.length >= 64){ - storeName = storeName.substring(0, 63); - } - - // refresh everything by simply removing - // any older stores - localServer.removeStore(storeName); - - // open/create the resource store - localServer.openStore(storeName); - var store = localServer.createStore(storeName); - this._store = store; - - // add our list of files to capture - var self = this; - this._currentFileIndex = 0; - this._cancelID = store.capture(this.listOfURLs, function(url, success, captureId){ - //console.debug("store.capture, url="+url+", success="+success); - if(!success && self.refreshing){ - self._cancelID = null; - self.refreshing = false; - var errorMsgs = []; - errorMsgs.push("Unable to capture: " + url); - callback(true, errorMsgs); - return; - }else if(success){ - self._currentFileIndex++; - } - - if(success && self._currentFileIndex >= self.listOfURLs.length){ - self._cancelID = null; - self.refreshing = false; - if(newVersion){ - dojox.storage.put("oldVersion", newVersion, null, - dojox.off.STORAGE_NAMESPACE); - } - dojox.storage.put("justDebugged", dojo.config.isDebug, null, - dojox.off.STORAGE_NAMESPACE); - callback(false, []); - } - }); - }, - - _getVersionInfo: function(callback){ - var justDebugged = dojox.storage.get("justDebugged", - dojox.off.STORAGE_NAMESPACE); - var oldVersion = dojox.storage.get("oldVersion", - dojox.off.STORAGE_NAMESPACE); - var newVersion = null; - - callback = dojo.hitch(this, callback); - - dojo.xhrGet({ - url: this.versionURL + "?browserbust=" + new Date().getTime(), - timeout: 5 * 1000, - handleAs: "javascript", - error: function(err){ - //console.warn("dojox.off.files._getVersionInfo, err=",err); - dojox.storage.remove("oldVersion", dojox.off.STORAGE_NAMESPACE); - dojox.storage.remove("justDebugged", dojox.off.STORAGE_NAMESPACE); - callback(oldVersion, newVersion, justDebugged); - }, - load: function(data){ - //console.warn("dojox.off.files._getVersionInfo, load=",data); - - // some servers incorrectly return 404's - // as a real page - if(data){ - newVersion = data; - } - - callback(oldVersion, newVersion, justDebugged); - } - }); - } -} - -} - -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"); - - - - - -// 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(); - -} - -if(!dojo._hasResource["dojox.off._common"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojox.off._common"] = true; -dojo.provide("dojox.off._common"); - - - - - -// Author: Brad Neuberg, bkn3@columbia.edu, http://codinginparadise.org - -// summary: -// dojox.off is the main object for offline applications. -dojo.mixin(dojox.off, { - // isOnline: boolean - // true if we are online, false if not - isOnline: false, - - // NET_CHECK: int - // For advanced usage; most developers can ignore this. - // Time in seconds on how often we should check the status of the - // network with an automatic background timer. The current default - // is 5 seconds. - NET_CHECK: 5, - - // STORAGE_NAMESPACE: String - // For advanced usage; most developers can ignore this. - // The namespace we use to save core data into Dojo Storage. - STORAGE_NAMESPACE: "_dot", - - // enabled: boolean - // For advanced usage; most developers can ignore this. - // Whether offline ability is enabled or not. Defaults to true. - enabled: true, - - // availabilityURL: String - // For advanced usage; most developers can ignore this. - // The URL to check for site availability. We do a GET request on - // this URL to check for site availability. By default we check for a - // simple text file in src/off/network_check.txt that has one value - // it, the value '1'. - availabilityURL: dojo.moduleUrl("dojox", "off/network_check.txt"), - - // goingOnline: boolean - // For advanced usage; most developers can ignore this. - // True if we are attempting to go online, false otherwise - goingOnline: false, - - // coreOpFailed: boolean - // For advanced usage; most developers can ignore this. - // A flag set by the Dojo Offline framework that indicates that the - // user denied some operation that required the offline cache or an - // operation failed in some critical way that was unrecoverable. For - // example, if the offline cache is Google Gears and we try to get a - // Gears database, a popup window appears asking the user whether they - // will approve or deny this request. If the user denies the request, - // and we are doing some operation that is core to Dojo Offline, then - // we set this flag to 'true'. This flag causes a 'fail fast' - // condition, turning off offline ability. - coreOpFailed: false, - - // doNetChecking: boolean - // For advanced usage; most developers can ignore this. - // Whether to have a timing interval in the background doing automatic - // network checks at regular intervals; the length of time between - // checks is controlled by dojox.off.NET_CHECK. Defaults to true. - doNetChecking: true, - - // hasOfflineCache: boolean - // For advanced usage; most developers can ignore this. - // Determines if an offline cache is available or installed; an - // offline cache is a facility that can truely cache offline - // resources, such as JavaScript, HTML, etc. in such a way that they - // won't be removed from the cache inappropriately like a browser - // cache would. If this is false then an offline cache will be - // installed. Only Google Gears is currently supported as an offline - // cache. Future possible offline caches include Firefox 3. - hasOfflineCache: null, - - // browserRestart: boolean - // For advanced usage; most developers can ignore this. - // If true, the browser must be restarted to register the existence of - // a new host added offline (from a call to addHostOffline); if false, - // then nothing is needed. - browserRestart: false, - - _STORAGE_APP_NAME: window.location.href.replace(/[^0-9A-Za-z_]/g, "_"), - - _initializeCalled: false, - _storageLoaded: false, - _pageLoaded: false, - - onLoad: function(){ - // summary: - // Called when Dojo Offline can be used. - // description: - // Do a dojo.connect to this to know when you can - // start using Dojo Offline: - // dojo.connect(dojox.off, "onLoad", myFunc); - }, - - onNetwork: function(type){ - // summary: - // Called when our on- or offline- status changes. - // description: - // If we move online, then this method is called with the - // value "online". If we move offline, then this method is - // called with the value "offline". You can connect to this - // method to do add your own behavior: - // - // dojo.connect(dojox.off, "onNetwork", someFunc) - // - // Note that if you are using the default Dojo Offline UI - // widget that most of the on- and off-line notification - // and syncing is automatically handled and provided to the - // user. - // type: String - // Either "online" or "offline". - }, - - initialize: function(){ /* void */ - // summary: - // Called when a Dojo Offline-enabled application is finished - // configuring Dojo Offline, and is ready for Dojo Offline to - // initialize itself. - // description: - // When an application has finished filling out the variables Dojo - // Offline needs to work, such as dojox.off.ui.appName, it must - // this method to tell Dojo Offline to initialize itself. - - // Note: - // This method is needed for a rare edge case. In some conditions, - // especially if we are dealing with a compressed Dojo build, the - // entire Dojo Offline subsystem might initialize itself and be - // running even before the JavaScript for an application has had a - // chance to run and configure Dojo Offline, causing Dojo Offline - // to have incorrect initialization parameters for a given app, - // such as no value for dojox.off.ui.appName. This method is - // provided to prevent this scenario, to slightly 'slow down' Dojo - // Offline so it can be configured before running off and doing - // its thing. - - //console.debug("dojox.off.initialize"); - this._initializeCalled = true; - - if(this._storageLoaded && this._pageLoaded){ - this._onLoad(); - } - }, - - goOffline: function(){ /* void */ - // summary: - // For advanced usage; most developers can ignore this. - // Manually goes offline, away from the network. - if((dojox.off.sync.isSyncing)||(this.goingOnline)){ return; } - - this.goingOnline = false; - this.isOnline = false; - }, - - goOnline: function(callback){ /* void */ - // summary: - // For advanced usage; most developers can ignore this. - // Attempts to go online. - // description: - // Attempts to go online, making sure this web application's web - // site is available. 'callback' is called asychronously with the - // result of whether we were able to go online or not. - // callback: Function - // An optional callback function that will receive one argument: - // whether the site is available or not and is boolean. If this - // function is not present we call dojo.xoff.onOnline instead if - // we are able to go online. - - //console.debug("goOnline"); - - if(dojox.off.sync.isSyncing || dojox.off.goingOnline){ - return; - } - - this.goingOnline = true; - this.isOnline = false; - - // see if can reach our web application's web site - this._isSiteAvailable(callback); - }, - - onFrameworkEvent: function(type /* String */, saveData /* Object? */){ - // summary: - // For advanced usage; most developers can ignore this. - // A standard event handler that can be attached to to find out - // about low-level framework events. Most developers will not need to - // attach to this method; it is meant for low-level information - // that can be useful for updating offline user-interfaces in - // exceptional circumstances. The default Dojo Offline UI - // widget takes care of most of these situations. - // type: String - // The type of the event: - // - // * "offlineCacheInstalled" - // An event that is fired when a user - // has installed an offline cache after the page has been loaded. - // If a user didn't have an offline cache when the page loaded, a - // UI of some kind might have prompted them to download one. This - // method is called if they have downloaded and installed an - // offline cache so a UI can reinitialize itself to begin using - // this offline cache. - // * "coreOperationFailed" - // Fired when a core operation during interaction with the - // offline cache is denied by the user. Some offline caches, such - // as Google Gears, prompts the user to approve or deny caching - // files, using the database, and more. If the user denies a - // request that is core to Dojo Offline's operation, we set - // dojox.off.coreOpFailed to true and call this method for - // listeners that would like to respond some how to Dojo Offline - // 'failing fast'. - // * "save" - // Called whenever the framework saves data into persistent - // storage. This could be useful for providing save feedback - // or providing appropriate error feedback if saving fails - // due to a user not allowing the save to occur - // saveData: Object? - // If the type was 'save', then a saveData object is provided with - // further save information. This object has the following properties: - // - // * status - dojox.storage.SUCCESS, dojox.storage.PENDING, dojox.storage.FAILED - // Whether the save succeeded, whether it is pending based on a UI - // dialog asking the user for permission, or whether it failed. - // - // * isCoreSave - boolean - // If true, then this save was for a core piece of data necessary - // for the functioning of Dojo Offline. If false, then it is a - // piece of normal data being saved for offline access. Dojo - // Offline will 'fail fast' if some core piece of data could not - // be saved, automatically setting dojox.off.coreOpFailed to - // 'true' and dojox.off.enabled to 'false'. - // - // * key - String - // The key that we are attempting to persist - // - // * value - Object - // The object we are trying to persist - // - // * namespace - String - // The Dojo Storage namespace we are saving this key/value pair - // into, such as "default", "Documents", "Contacts", etc. - // Optional. - if(type == "save"){ - if(saveData.isCoreSave && (saveData.status == dojox.storage.FAILED)){ - dojox.off.coreOpFailed = true; - dojox.off.enabled = false; - - // FIXME: Stop the background network thread - dojox.off.onFrameworkEvent("coreOperationFailed"); - } - }else if(type == "coreOperationFailed"){ - dojox.off.coreOpFailed = true; - dojox.off.enabled = false; - // FIXME: Stop the background network thread - } - }, - - _checkOfflineCacheAvailable: function(callback){ - // is a true, offline cache running on this machine? - this.hasOfflineCache = dojo.isGears; - - callback(); - }, - - _onLoad: function(){ - //console.debug("dojox.off._onLoad"); - - // both local storage and the page are finished loading - - // cache the Dojo JavaScript -- just use the default dojo.js - // name for the most common scenario - // FIXME: TEST: Make sure syncing doesn't break if dojo.js - // can't be found, or report an error to developer - dojox.off.files.cache(dojo.moduleUrl("dojo", "dojo.js")); - - // pull in the files needed by Dojo - this._cacheDojoResources(); - - // FIXME: need to pull in the firebug lite files here! - // workaround or else we will get an error on page load - // from Dojo that it can't find 'console.debug' for optimized builds - // dojox.off.files.cache(dojo.config.baseRelativePath + "src/debug.js"); - - // make sure that resources needed by all of our underlying - // Dojo Storage storage providers will be available - // offline - dojox.off.files.cache(dojox.storage.manager.getResourceList()); - - // slurp the page if the end-developer wants that - dojox.off.files._slurp(); - - // see if we have an offline cache; when done, move - // on to the rest of our startup tasks - this._checkOfflineCacheAvailable(dojo.hitch(this, "_onOfflineCacheChecked")); - }, - - _onOfflineCacheChecked: function(){ - // this method is part of our _onLoad series of startup tasks - - // if we have an offline cache, see if we have been added to the - // list of available offline web apps yet - if(this.hasOfflineCache && this.enabled){ - // load framework data; when we are finished, continue - // initializing ourselves - this._load(dojo.hitch(this, "_finishStartingUp")); - }else if(this.hasOfflineCache && !this.enabled){ - // we have an offline cache, but it is disabled for some reason - // perhaps due to the user denying a core operation - this._finishStartingUp(); - }else{ - this._keepCheckingUntilInstalled(); - } - }, - - _keepCheckingUntilInstalled: function(){ - // this method is part of our _onLoad series of startup tasks - - // kick off a background interval that keeps - // checking to see if an offline cache has been - // installed since this page loaded - - // FIXME: Gears: See if we are installed somehow after the - // page has been loaded - - // now continue starting up - this._finishStartingUp(); - }, - - _finishStartingUp: function(){ - //console.debug("dojox.off._finishStartingUp"); - - // this method is part of our _onLoad series of startup tasks - - if(!this.hasOfflineCache){ - this.onLoad(); - }else if(this.enabled){ - // kick off a thread to check network status on - // a regular basis - this._startNetworkThread(); - - // try to go online - this.goOnline(dojo.hitch(this, function(){ - //console.debug("Finished trying to go online"); - // indicate we are ready to be used - dojox.off.onLoad(); - })); - }else{ // we are disabled or a core operation failed - if(this.coreOpFailed){ - this.onFrameworkEvent("coreOperationFailed"); - }else{ - this.onLoad(); - } - } - }, - - _onPageLoad: function(){ - //console.debug("dojox.off._onPageLoad"); - this._pageLoaded = true; - - if(this._storageLoaded && this._initializeCalled){ - this._onLoad(); - } - }, - - _onStorageLoad: function(){ - //console.debug("dojox.off._onStorageLoad"); - this._storageLoaded = true; - - // were we able to initialize storage? if - // not, then this is a core operation, and - // let's indicate we will need to fail fast - if(!dojox.storage.manager.isAvailable() - && dojox.storage.manager.isInitialized()){ - this.coreOpFailed = true; - this.enabled = false; - } - - if(this._pageLoaded && this._initializeCalled){ - this._onLoad(); - } - }, - - _isSiteAvailable: function(callback){ - // summary: - // Determines if our web application's website is available. - // description: - // This method will asychronously determine if our web - // application's web site is available, which is a good proxy for - // network availability. The URL dojox.off.availabilityURL is - // used, which defaults to this site's domain name (ex: - // foobar.com). We check for dojox.off.AVAILABILITY_TIMEOUT (in - // seconds) and abort after that - // callback: Function - // An optional callback function that will receive one argument: - // whether the site is available or not and is boolean. If this - // function is not present we call dojox.off.onNetwork instead if we - // are able to go online. - dojo.xhrGet({ - url: this._getAvailabilityURL(), - handleAs: "text", - timeout: this.NET_CHECK * 1000, - error: dojo.hitch(this, function(err){ - //console.debug("dojox.off._isSiteAvailable.error: " + err); - this.goingOnline = false; - this.isOnline = false; - if(callback){ callback(false); } - }), - load: dojo.hitch(this, function(data){ - //console.debug("dojox.off._isSiteAvailable.load, data="+data); - this.goingOnline = false; - this.isOnline = true; - - if(callback){ callback(true); - }else{ this.onNetwork("online"); } - }) - }); - }, - - _startNetworkThread: function(){ - //console.debug("startNetworkThread"); - - // kick off a thread that does periodic - // checks on the status of the network - if(!this.doNetChecking){ - return; - } - - window.setInterval(dojo.hitch(this, function(){ - var d = dojo.xhrGet({ - url: this._getAvailabilityURL(), - handleAs: "text", - timeout: this.NET_CHECK * 1000, - error: dojo.hitch(this, - function(err){ - if(this.isOnline){ - this.isOnline = false; - - // FIXME: xhrGet() is not - // correctly calling abort - // on the XHR object when - // it times out; fix inside - // there instead of externally - // here - try{ - if(typeof d.ioArgs.xhr.abort == "function"){ - d.ioArgs.xhr.abort(); - } - }catch(e){} - - // if things fell in the middle of syncing, - // stop syncing - dojox.off.sync.isSyncing = false; - - this.onNetwork("offline"); - } - } - ), - load: dojo.hitch(this, - function(data){ - if(!this.isOnline){ - this.isOnline = true; - this.onNetwork("online"); - } - } - ) - }); - - }), this.NET_CHECK * 1000); - }, - - _getAvailabilityURL: function(){ - var url = this.availabilityURL.toString(); - - // bust the browser's cache to make sure we are really talking to - // the server - if(url.indexOf("?") == -1){ - url += "?"; - }else{ - url += "&"; - } - url += "browserbust=" + new Date().getTime(); - - return url; - }, - - _onOfflineCacheInstalled: function(){ - this.onFrameworkEvent("offlineCacheInstalled"); - }, - - _cacheDojoResources: function(){ - // if we are a non-optimized build, then the core Dojo bootstrap - // system was loaded as separate JavaScript files; - // add these to our offline cache list. these are - // loaded before the dojo.require() system exists - - // FIXME: create a better mechanism in the Dojo core to - // expose whether you are dealing with an optimized build; - // right now we just scan the SCRIPT tags attached to this - // page and see if there is one for _base/_loader/bootstrap.js - var isOptimizedBuild = true; - dojo.forEach(dojo.query("script"), function(i){ - var src = i.getAttribute("src"); - if(!src){ return; } - - if(src.indexOf("_base/_loader/bootstrap.js") != -1){ - isOptimizedBuild = false; - } - }); - - if(!isOptimizedBuild){ - dojox.off.files.cache(dojo.moduleUrl("dojo", "_base.js").uri); - dojox.off.files.cache(dojo.moduleUrl("dojo", "_base/_loader/loader.js").uri); - dojox.off.files.cache(dojo.moduleUrl("dojo", "_base/_loader/bootstrap.js").uri); - - // FIXME: pull in the host environment file in a more generic way - // for other host environments - dojox.off.files.cache(dojo.moduleUrl("dojo", "_base/_loader/hostenv_browser.js").uri); - } - - // add anything that was brought in with a - // dojo.require() that resulted in a JavaScript - // URL being fetched - - // FIXME: modify dojo/_base/_loader/loader.js to - // expose a public API to get this information - - for(var i = 0; i < dojo._loadedUrls.length; i++){ - dojox.off.files.cache(dojo._loadedUrls[i]); - } - - // FIXME: add the standard Dojo CSS file - }, - - _save: function(){ - // summary: - // Causes the Dojo Offline framework to save its configuration - // data into local storage. - }, - - _load: function(callback){ - // summary: - // Causes the Dojo Offline framework to load its configuration - // data from local storage - dojox.off.sync._load(callback); - } -}); - - -// wait until the storage system is finished loading -dojox.storage.manager.addOnLoad(dojo.hitch(dojox.off, "_onStorageLoad")); - -// wait until the page is finished loading -dojo.addOnLoad(dojox.off, "_onPageLoad"); - -} - -if(!dojo._hasResource["dojox.off"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojox.off"] = true; -dojo.provide("dojox.off"); - - -} - -if(!dojo._hasResource["dojox.off.ui"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojox.off.ui"] = true; -dojo.provide("dojox.off.ui"); - - - - - -// Author: Brad Neuberg, bkn3@columbia.edu, http://codinginparadise.org - -// summary: -// dojox.off.ui provides a standard, -// default user-interface for a -// Dojo Offline Widget that can easily -// be dropped into applications that would -// like to work offline. -dojo.mixin(dojox.off.ui, { - // appName: String - // This application's name, such as "Foobar". Note that - // this is a string, not HTML, so embedded markup will - // not work, including entities. Only the following - // characters are allowed: numbers, letters, and spaces. - // You must set this property. - appName: "setme", - - // autoEmbed: boolean - // For advanced usage; most developers can ignore this. - // Whether to automatically auto-embed the default Dojo Offline - // widget into this page; default is true. - autoEmbed: true, - - // autoEmbedID: String - // For advanced usage; most developers can ignore this. - // The ID of the DOM element that will contain our - // Dojo Offline widget; defaults to the ID 'dot-widget'. - autoEmbedID: "dot-widget", - - // runLink: String - // For advanced usage; most developers can ignore this. - // The URL that should be navigated to to run this - // application offline; this will be placed inside of a - // link that the user can drag to their desktop and double - // click. Note that this URL must exactly match the URL - // of the main page of our resource that is offline for - // it to be retrieved from the offline cache correctly. - // For example, if you have cached your main page as - // http://foobar.com/index.html, and you set this to - // http://www.foobar.com/index.html, the run link will - // not work. By default this value is automatically set to - // the URL of this page, so it does not need to be set - // manually unless you have unusual needs. - runLink: window.location.href, - - // runLinkTitle: String - // For advanced usage; most developers can ignore this. - // The text that will be inside of the link that a user - // can drag to their desktop to run this application offline. - // By default this is automatically set to "Run " plus your - // application's name. - runLinkTitle: "Run Application", - - // learnHowPath: String - // For advanced usage; most developers can ignore this. - // The path to a web page that has information on - // how to use this web app offline; defaults to - // src/off/ui-template/learnhow.html, relative to - // your Dojo installation. Make sure to set - // dojo.to.ui.customLearnHowPath to true if you want - // a custom Learn How page. - learnHowPath: dojo.moduleUrl("dojox", "off/resources/learnhow.html"), - - // customLearnHowPath: boolean - // For advanced usage; most developers can ignore this. - // Whether the developer is using their own custom page - // for the Learn How instructional page; defaults to false. - // Use in conjunction with dojox.off.ui.learnHowPath. - customLearnHowPath: false, - - htmlTemplatePath: dojo.moduleUrl("dojox", "off/resources/offline-widget.html").uri, - cssTemplatePath: dojo.moduleUrl("dojox", "off/resources/offline-widget.css").uri, - onlineImagePath: dojo.moduleUrl("dojox", "off/resources/greenball.png").uri, - offlineImagePath: dojo.moduleUrl("dojox", "off/resources/redball.png").uri, - rollerImagePath: dojo.moduleUrl("dojox", "off/resources/roller.gif").uri, - checkmarkImagePath: dojo.moduleUrl("dojox", "off/resources/checkmark.png").uri, - learnHowJSPath: dojo.moduleUrl("dojox", "off/resources/learnhow.js").uri, - - _initialized: false, - - onLoad: function(){ - // summary: - // A function that should be connected to allow your - // application to know when Dojo Offline, the page, and - // the Offline Widget are all initialized and ready to be - // used: - // - // dojo.connect(dojox.off.ui, "onLoad", someFunc) - }, - - _initialize: function(){ - //console.debug("dojox.off.ui._initialize"); - - // make sure our app name is correct - if(this._validateAppName(this.appName) == false){ - alert("You must set dojox.off.ui.appName; it can only contain " - + "letters, numbers, and spaces; right now it " - + "is incorrectly set to '" + dojox.off.ui.appName + "'"); - dojox.off.enabled = false; - return; - } - - // set our run link text to its default - this.runLinkText = "Run " + this.appName; - - // setup our event listeners for Dojo Offline events - // to update our UI - dojo.connect(dojox.off, "onNetwork", this, "_onNetwork"); - dojo.connect(dojox.off.sync, "onSync", this, "_onSync"); - - // cache our default UI resources - dojox.off.files.cache([ - this.htmlTemplatePath, - this.cssTemplatePath, - this.onlineImagePath, - this.offlineImagePath, - this.rollerImagePath, - this.checkmarkImagePath - ]); - - // embed the offline widget UI - if(this.autoEmbed){ - this._doAutoEmbed(); - } - }, - - _doAutoEmbed: function(){ - // fetch our HTML for the offline widget - - // dispatch the request - dojo.xhrGet({ - url: this.htmlTemplatePath, - handleAs: "text", - error: function(err){ - dojox.off.enabled = false; - err = err.message||err; - alert("Error loading the Dojo Offline Widget from " - + this.htmlTemplatePath + ": " + err); - }, - load: dojo.hitch(this, this._templateLoaded) - }); - }, - - _templateLoaded: function(data){ - //console.debug("dojox.off.ui._templateLoaded"); - // inline our HTML - var container = dojo.byId(this.autoEmbedID); - if(container){ container.innerHTML = data; } - - // fill out our image paths - this._initImages(); - - // update our network indicator status ball - this._updateNetIndicator(); - - // update our 'Learn How' text - this._initLearnHow(); - - this._initialized = true; - - // check offline cache settings - if(!dojox.off.hasOfflineCache){ - this._showNeedsOfflineCache(); - return; - } - - // check to see if we need a browser restart - // to be able to use this web app offline - if(dojox.off.hasOfflineCache && dojox.off.browserRestart){ - this._needsBrowserRestart(); - return; - }else{ - var browserRestart = dojo.byId("dot-widget-browser-restart"); - if(browserRestart){ browserRestart.style.display = "none"; } - } - - // update our sync UI - this._updateSyncUI(); - - // register our event listeners for our main buttons - this._initMainEvtHandlers(); - - // if offline functionality is disabled, disable everything - this._setOfflineEnabled(dojox.off.enabled); - - // update our UI based on the state of the network - this._onNetwork(dojox.off.isOnline ? "online" : "offline"); - - // try to go online - this._testNet(); - }, - - _testNet: function(){ - dojox.off.goOnline(dojo.hitch(this, function(isOnline){ - //console.debug("testNet callback, isOnline="+isOnline); - - // display our online/offline results - this._onNetwork(isOnline ? "online" : "offline"); - - // indicate that our default UI - // and Dojo Offline are now ready to - // be used - this.onLoad(); - })); - }, - - _updateNetIndicator: function(){ - var onlineImg = dojo.byId("dot-widget-network-indicator-online"); - var offlineImg = dojo.byId("dot-widget-network-indicator-offline"); - var titleText = dojo.byId("dot-widget-title-text"); - - if(onlineImg && offlineImg){ - if(dojox.off.isOnline == true){ - onlineImg.style.display = "inline"; - offlineImg.style.display = "none"; - }else{ - onlineImg.style.display = "none"; - offlineImg.style.display = "inline"; - } - } - - if(titleText){ - if(dojox.off.isOnline){ - titleText.innerHTML = "Online"; - }else{ - titleText.innerHTML = "Offline"; - } - } - }, - - _initLearnHow: function(){ - var learnHow = dojo.byId("dot-widget-learn-how-link"); - - if(!learnHow){ return; } - - if(!this.customLearnHowPath){ - // add parameters to URL so the Learn How page - // can customize itself and display itself - // correctly based on framework settings - var dojoPath = dojo.config.baseRelativePath; - this.learnHowPath += "?appName=" + encodeURIComponent(this.appName) - + "&hasOfflineCache=" + dojox.off.hasOfflineCache - + "&runLink=" + encodeURIComponent(this.runLink) - + "&runLinkText=" + encodeURIComponent(this.runLinkText) - + "&baseRelativePath=" + encodeURIComponent(dojoPath); - - // cache our Learn How JavaScript page and - // the HTML version with full query parameters - // so it is available offline without a cache miss - dojox.off.files.cache(this.learnHowJSPath); - dojox.off.files.cache(this.learnHowPath); - } - - learnHow.setAttribute("href", this.learnHowPath); - - var appName = dojo.byId("dot-widget-learn-how-app-name"); - - if(!appName){ return; } - - appName.innerHTML = ""; - appName.appendChild(document.createTextNode(this.appName)); - }, - - _validateAppName: function(appName){ - if(!appName){ return false; } - - return (/^[a-z0-9 ]*$/i.test(appName)); - }, - - _updateSyncUI: function(){ - var roller = dojo.byId("dot-roller"); - var checkmark = dojo.byId("dot-success-checkmark"); - var syncMessages = dojo.byId("dot-sync-messages"); - var details = dojo.byId("dot-sync-details"); - var cancel = dojo.byId("dot-sync-cancel"); - - if(dojox.off.sync.isSyncing){ - this._clearSyncMessage(); - - if(roller){ roller.style.display = "inline"; } - - if(checkmark){ checkmark.style.display = "none"; } - - if(syncMessages){ - dojo.removeClass(syncMessages, "dot-sync-error"); - } - - if(details){ details.style.display = "none"; } - - if(cancel){ cancel.style.display = "inline"; } - }else{ - if(roller){ roller.style.display = "none"; } - - if(cancel){ cancel.style.display = "none"; } - - if(syncMessages){ - dojo.removeClass(syncMessages, "dot-sync-error"); - } - } - }, - - _setSyncMessage: function(message){ - var syncMessage = dojo.byId("dot-sync-messages"); - if(syncMessage){ - // when used with Google Gears pre-release in Firefox/Mac OS X, - // the browser would crash when testing in Moxie - // if we set the message this way for some reason. - // Brad Neuberg, bkn3@columbia.edu - //syncMessage.innerHTML = message; - - while(syncMessage.firstChild){ - syncMessage.removeChild(syncMessage.firstChild); - } - syncMessage.appendChild(document.createTextNode(message)); - } - }, - - _clearSyncMessage: function(){ - this._setSyncMessage(""); - }, - - _initImages: function(){ - var onlineImg = dojo.byId("dot-widget-network-indicator-online"); - if(onlineImg){ - onlineImg.setAttribute("src", this.onlineImagePath); - } - - var offlineImg = dojo.byId("dot-widget-network-indicator-offline"); - if(offlineImg){ - offlineImg.setAttribute("src", this.offlineImagePath); - } - - var roller = dojo.byId("dot-roller"); - if(roller){ - roller.setAttribute("src", this.rollerImagePath); - } - - var checkmark = dojo.byId("dot-success-checkmark"); - if(checkmark){ - checkmark.setAttribute("src", this.checkmarkImagePath); - } - }, - - _showDetails: function(evt){ - // cancel the button's default behavior - evt.preventDefault(); - evt.stopPropagation(); - - if(!dojox.off.sync.details.length){ - return; - } - - // determine our HTML message to display - var html = ""; - html += "Sync Details"; - html += "

Sync Details

\n"; - html += "
    \n"; - for(var i = 0; i < dojox.off.sync.details.length; i++){ - html += "
  • "; - html += dojox.off.sync.details[i]; - html += "
  • "; - } - html += "
\n"; - html += "" - + "Close Window" - + "\n"; - html += ""; - - // open a popup window with this message - var windowParams = "height=400,width=600,resizable=true," - + "scrollbars=true,toolbar=no,menubar=no," - + "location=no,directories=no,dependent=yes"; - - var popup = window.open("", "SyncDetails", windowParams); - - if(!popup){ // aggressive popup blocker - alert("Please allow popup windows for this domain; can't display sync details window"); - return; - } - - popup.document.open(); - popup.document.write(html); - popup.document.close(); - - // put the focus on the popup window - if(popup.focus){ - popup.focus(); - } - }, - - _cancel: function(evt){ - // cancel the button's default behavior - evt.preventDefault(); - evt.stopPropagation(); - - dojox.off.sync.cancel(); - }, - - _needsBrowserRestart: function(){ - var browserRestart = dojo.byId("dot-widget-browser-restart"); - if(browserRestart){ - dojo.addClass(browserRestart, "dot-needs-browser-restart"); - } - - var appName = dojo.byId("dot-widget-browser-restart-app-name"); - if(appName){ - appName.innerHTML = ""; - appName.appendChild(document.createTextNode(this.appName)); - } - - var status = dojo.byId("dot-sync-status"); - if(status){ - status.style.display = "none"; - } - }, - - _showNeedsOfflineCache: function(){ - var widgetContainer = dojo.byId("dot-widget-container"); - if(widgetContainer){ - dojo.addClass(widgetContainer, "dot-needs-offline-cache"); - } - }, - - _hideNeedsOfflineCache: function(){ - var widgetContainer = dojo.byId("dot-widget-container"); - if(widgetContainer){ - dojo.removeClass(widgetContainer, "dot-needs-offline-cache"); - } - }, - - _initMainEvtHandlers: function(){ - var detailsButton = dojo.byId("dot-sync-details-button"); - if(detailsButton){ - dojo.connect(detailsButton, "onclick", this, this._showDetails); - } - var cancelButton = dojo.byId("dot-sync-cancel-button"); - if(cancelButton){ - dojo.connect(cancelButton, "onclick", this, this._cancel); - } - }, - - _setOfflineEnabled: function(enabled){ - var elems = []; - elems.push(dojo.byId("dot-sync-status")); - - for(var i = 0; i < elems.length; i++){ - if(elems[i]){ - elems[i].style.visibility = - (enabled ? "visible" : "hidden"); - } - } - }, - - _syncFinished: function(){ - this._updateSyncUI(); - - var checkmark = dojo.byId("dot-success-checkmark"); - var details = dojo.byId("dot-sync-details"); - - if(dojox.off.sync.successful == true){ - this._setSyncMessage("Sync Successful"); - if(checkmark){ checkmark.style.display = "inline"; } - }else if(dojox.off.sync.cancelled == true){ - this._setSyncMessage("Sync Cancelled"); - - if(checkmark){ checkmark.style.display = "none"; } - }else{ - this._setSyncMessage("Sync Error"); - - var messages = dojo.byId("dot-sync-messages"); - if(messages){ - dojo.addClass(messages, "dot-sync-error"); - } - - if(checkmark){ checkmark.style.display = "none"; } - } - - if(dojox.off.sync.details.length && details){ - details.style.display = "inline"; - } - }, - - _onFrameworkEvent: function(type, saveData){ - if(type == "save"){ - if(saveData.status == dojox.storage.FAILED && !saveData.isCoreSave){ - alert("Please increase the amount of local storage available " - + "to this application"); - if(dojox.storage.hasSettingsUI()){ - dojox.storage.showSettingsUI(); - } - - // FIXME: Be able to know if storage size has changed - // due to user configuration - } - }else if(type == "coreOperationFailed"){ - console.log("Application does not have permission to use Dojo Offline"); - - if(!this._userInformed){ - alert("This application will not work if Google Gears is not allowed to run"); - this._userInformed = true; - } - }else if(type == "offlineCacheInstalled"){ - // clear out the 'needs offline cache' info - this._hideNeedsOfflineCache(); - - // check to see if we need a browser restart - // to be able to use this web app offline - if(dojox.off.hasOfflineCache == true - && dojox.off.browserRestart == true){ - this._needsBrowserRestart(); - return; - }else{ - var browserRestart = dojo.byId("dot-widget-browser-restart"); - if(browserRestart){ - browserRestart.style.display = "none"; - } - } - - // update our sync UI - this._updateSyncUI(); - - // register our event listeners for our main buttons - this._initMainEvtHandlers(); - - // if offline is disabled, disable everything - this._setOfflineEnabled(dojox.off.enabled); - - // try to go online - this._testNet(); - } - }, - - _onSync: function(type){ - //console.debug("ui, onSync="+type); - switch(type){ - case "start": - this._updateSyncUI(); - break; - - case "refreshFiles": - this._setSyncMessage("Downloading UI..."); - break; - - case "upload": - this._setSyncMessage("Uploading new data..."); - break; - - case "download": - this._setSyncMessage("Downloading new data..."); - break; - - case "finished": - this._syncFinished(); - break; - - case "cancel": - this._setSyncMessage("Canceling Sync..."); - break; - - default: - dojo.warn("Programming error: " - + "Unknown sync type in dojox.off.ui: " + type); - break; - } - }, - - _onNetwork: function(type){ - // summary: - // Called when we go on- or off-line - // description: - // When we go online or offline, this method is called to update - // our UI. Default behavior is to update the Offline - // Widget UI and to attempt a synchronization. - // type: String - // "online" if we just moved online, and "offline" if we just - // moved offline. - - if(!this._initialized){ return; } - - // update UI - this._updateNetIndicator(); - - if(type == "offline"){ - this._setSyncMessage("You are working offline"); - - // clear old details - var details = dojo.byId("dot-sync-details"); - if(details){ details.style.display = "none"; } - - // if we fell offline during a sync, hide - // the sync info - this._updateSyncUI(); - }else{ // online - // synchronize, but pause for a few seconds - // so that the user can orient themselves - if(dojox.off.sync.autoSync){ - if(dojo.isAIR){ - window.setTimeout(function(){dojox.off.sync.synchronize();}, 1000); - }else{ - window.setTimeout(dojox._scopeName + ".off.sync.synchronize()", 1000); - } - } - } - } -}); - -// register ourselves for low-level framework events -dojo.connect(dojox.off, "onFrameworkEvent", dojox.off.ui, "_onFrameworkEvent"); - -// start our magic when the Dojo Offline framework is ready to go -dojo.connect(dojox.off, "onLoad", dojox.off.ui, dojox.off.ui._initialize); - -} - -if(!dojo._hasResource["dojox.off.offline"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojox.off.offline"] = true; -dojo.provide("dojox.off.offline"); - - - - - - - -} - diff --git a/includes/js/dojox/off/resources/checkmark.png b/includes/js/dojox/off/resources/checkmark.png deleted file mode 100644 index a0ffbb1..0000000 Binary files a/includes/js/dojox/off/resources/checkmark.png and /dev/null differ diff --git a/includes/js/dojox/off/resources/greenball.png b/includes/js/dojox/off/resources/greenball.png deleted file mode 100644 index 520b6a6..0000000 Binary files a/includes/js/dojox/off/resources/greenball.png and /dev/null differ diff --git a/includes/js/dojox/off/resources/learnhow.html b/includes/js/dojox/off/resources/learnhow.html deleted file mode 100644 index 2833fcc..0000000 --- a/includes/js/dojox/off/resources/learnhow.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - -
-

Want to use Application offline?

- -

It's simple with Dojo Offline! Dojo Offline is a free open source utility that makes it easy - for this web application to work, even if you're offline. Now you can - access your data even when away from the network!

- -

Dojo Offline is an open source project brought to you by - Dojo, SitePen, - and Brad Neuberg. It incorporates - technologies created by Google.

- -

To get started:

- -
    -
  1. - Download Gears, a small, open source utility created by Google that allows this web site - to work offline. This tool is safe and secure for your machine, and only takes - a few seconds to download. -
  2. -
  3. - Once downloaded, run the installer. Restart your web browser when finished installing. -
  4. - - -
-
- - \ No newline at end of file diff --git a/includes/js/dojox/off/resources/learnhow.js b/includes/js/dojox/off/resources/learnhow.js deleted file mode 100644 index 82d5506..0000000 --- a/includes/js/dojox/off/resources/learnhow.js +++ /dev/null @@ -1,43 +0,0 @@ -window.onload = function(){ - // get the app name from our URL - var href = window.location.href; - var matches = href.match(/appName=([a-z0-9 \%]*)/i); - var appName = "Application"; - if(matches && matches.length > 0){ - appName = decodeURIComponent(matches[1]); - } - - // set it in our UI - var appNameSpan = document.getElementById("dot-learn-how-app-name"); - appNameSpan.innerHTML = ""; - appNameSpan.appendChild(document.createTextNode(appName)); - - // if we need an offline cache, and we already have one installed, - // update the UI - matches = href.match(/hasOfflineCache=(true|false)/); - var hasOfflineCache = false; - if(matches && matches.length > 0){ - hasOfflineCache = matches[1]; - // convert to boolean - hasOfflineCache = (hasOfflineCache == "true") ? true : false; - } - if(hasOfflineCache == true){ - // delete the download and install steps - var downloadStep = document.getElementById("dot-download-step"); - var installStep = document.getElementById("dot-install-step"); - downloadStep.parentNode.removeChild(downloadStep); - installStep.parentNode.removeChild(installStep); - } - - // get our run link info and update the UI - matches = href.match(/runLink=([^\&]*)\&runLinkText=([^\&]*)/); - if(matches && matches.length > 0){ - var runLink = decodeURIComponent(matches[1]); - var runLinkElem = document.getElementById("dot-learn-how-run-link"); - runLinkElem.setAttribute("href", runLink); - - var runLinkText = decodeURIComponent(matches[2]); - runLinkElem.innerHTML = ""; - runLinkElem.appendChild(document.createTextNode(runLinkText)); - } -} diff --git a/includes/js/dojox/off/resources/offline-widget.css b/includes/js/dojox/off/resources/offline-widget.css deleted file mode 100644 index 3d095e9..0000000 --- a/includes/js/dojox/off/resources/offline-widget.css +++ /dev/null @@ -1,88 +0,0 @@ - -#dot-widget-container{ - - width: 13em; - height: auto; - border: 2px solid #CDDDE9; - position: relative; - visibility: visible !important; -} -#dot-widget-title-bar{ - background-color: #CDDDE9; - padding-top: 0.2em; - padding-bottom: 0.2em; -} -#dot-widget-network-indicator{ - height: 8px; - width: 8px; - padding-left: 0.3em; -} -#dot-widget-title-text{ - vertical-align: middle; - font-weight: bold; - font-size: 14pt; - padding-left: 2px; -} -#dot-widget-contents{ - padding: 8px 5px 8px 5px; -} -#dot-widget-learn-how{ - font-size: 11pt; -} -#dot-sync-cancel, -#dot-sync-status{ - font-size: 11pt; -} -#dot-success-checkmark{ - display: none; -} -#dot-roller{ - display: none; - padding-right: 4px; -} -.dot-sync-error{ - color: red; -} -#dot-sync-details{ - display: none; - padding-left: 0.2em; -} -#dot-sync-status{ - height: 2em; - margin-top: 0.8em; - margin-bottom: 0.8em; -} -.dot-needs-offline-cache #dot-widget-learn-how, -.dot-needs-browser-restart{ - text-align: center; - line-height: 1.2; - font-size: 16pt !important; -} -.dot-needs-offline-cache #dot-sync-status, -.dot-needs-offline-cache #dot-widget-browser-restart{ - display: none; -} -.dot-needs-browser-restart{ - font-size: 14pt !important; - padding-bottom: 1em; - padding-top: 1em; -} -#dot-learn-how-body{ - padding: 3em; - background-color: #CDDDE9; -} -#dot-learn-how-contents{ - border: 1px solid black; - background-color: white; - padding: 0.4em 0.6em 0.4em 0.6em; - font-size: 16pt; -} -#dot-learn-how-contents h1{ - font-size: 24pt; -} -#dot-learn-how-contents h2{ - font-size: 18pt; -} -#dot-learn-how-contents li{ - padding-bottom: 0.6em; -} diff --git a/includes/js/dojox/off/resources/offline-widget.css.commented.css b/includes/js/dojox/off/resources/offline-widget.css.commented.css deleted file mode 100644 index 374a43b..0000000 --- a/includes/js/dojox/off/resources/offline-widget.css.commented.css +++ /dev/null @@ -1,112 +0,0 @@ -/** Offline Widget Styles */ - -#dot-widget-container{ - /** - Keep these as EMs so widget reflows fluidly based on - user-font size settings - */ - width: 13em; - height: auto; - border: 2px solid #CDDDE9; /* light tundra blue */ - position: relative; - visibility: visible !important; -} - -#dot-widget-title-bar{ - background-color: #CDDDE9; /* light tundra blue */ - padding-top: 0.2em; - padding-bottom: 0.2em; -} - -#dot-widget-network-indicator{ - height: 8px; - width: 8px; - padding-left: 0.3em; -} - -#dot-widget-title-text{ - vertical-align: middle; - font-weight: bold; - font-size: 14pt; - padding-left: 2px; -} - -#dot-widget-contents{ - padding: 8px 5px 8px 5px; -} - -#dot-widget-learn-how{ - font-size: 11pt; -} - -#dot-sync-cancel, -#dot-sync-status{ - font-size: 11pt; -} - -#dot-success-checkmark{ - display: none; -} - -#dot-roller{ - display: none; - padding-right: 4px; -} - -.dot-sync-error{ - color: red; -} - -#dot-sync-details{ - display: none; - padding-left: 0.2em; -} - -#dot-sync-status{ - height: 2em; - margin-top: 0.8em; - margin-bottom: 0.8em; -} - -.dot-needs-offline-cache #dot-widget-learn-how, -.dot-needs-browser-restart{ - text-align: center; - line-height: 1.2; - font-size: 16pt !important; -} - -.dot-needs-offline-cache #dot-sync-status, -.dot-needs-offline-cache #dot-widget-browser-restart{ - display: none; -} - -.dot-needs-browser-restart{ - font-size: 14pt !important; - padding-bottom: 1em; - padding-top: 1em; -} - -/** Learn How Page Styles */ -#dot-learn-how-body{ - padding: 3em; - background-color: #CDDDE9; /* light tundra blue */ -} - -#dot-learn-how-contents{ - border: 1px solid black; - background-color: white; - padding: 0.4em 0.6em 0.4em 0.6em; - font-size: 16pt; -} - -#dot-learn-how-contents h1{ - font-size: 24pt; -} - -#dot-learn-how-contents h2{ - font-size: 18pt; -} - -#dot-learn-how-contents li{ - padding-bottom: 0.6em; -} diff --git a/includes/js/dojox/off/resources/offline-widget.html b/includes/js/dojox/off/resources/offline-widget.html deleted file mode 100644 index 5791644..0000000 --- a/includes/js/dojox/off/resources/offline-widget.html +++ /dev/null @@ -1,40 +0,0 @@ - - - \ No newline at end of file diff --git a/includes/js/dojox/off/resources/redball.png b/includes/js/dojox/off/resources/redball.png deleted file mode 100644 index cc224c3..0000000 Binary files a/includes/js/dojox/off/resources/redball.png and /dev/null differ diff --git a/includes/js/dojox/off/resources/roller.gif b/includes/js/dojox/off/resources/roller.gif deleted file mode 100644 index 24a3a24..0000000 Binary files a/includes/js/dojox/off/resources/roller.gif and /dev/null differ 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(); - -} diff --git a/includes/js/dojox/off/ui.js b/includes/js/dojox/off/ui.js deleted file mode 100644 index 40f33c4..0000000 --- a/includes/js/dojox/off/ui.js +++ /dev/null @@ -1,622 +0,0 @@ -if(!dojo._hasResource["dojox.off.ui"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojox.off.ui"] = true; -dojo.provide("dojox.off.ui"); - -dojo.require("dojox.storage.Provider"); -dojo.require("dojox.storage.manager"); -dojo.require("dojox.storage.GearsStorageProvider"); - -// Author: Brad Neuberg, bkn3@columbia.edu, http://codinginparadise.org - -// summary: -// dojox.off.ui provides a standard, -// default user-interface for a -// Dojo Offline Widget that can easily -// be dropped into applications that would -// like to work offline. -dojo.mixin(dojox.off.ui, { - // appName: String - // This application's name, such as "Foobar". Note that - // this is a string, not HTML, so embedded markup will - // not work, including entities. Only the following - // characters are allowed: numbers, letters, and spaces. - // You must set this property. - appName: "setme", - - // autoEmbed: boolean - // For advanced usage; most developers can ignore this. - // Whether to automatically auto-embed the default Dojo Offline - // widget into this page; default is true. - autoEmbed: true, - - // autoEmbedID: String - // For advanced usage; most developers can ignore this. - // The ID of the DOM element that will contain our - // Dojo Offline widget; defaults to the ID 'dot-widget'. - autoEmbedID: "dot-widget", - - // runLink: String - // For advanced usage; most developers can ignore this. - // The URL that should be navigated to to run this - // application offline; this will be placed inside of a - // link that the user can drag to their desktop and double - // click. Note that this URL must exactly match the URL - // of the main page of our resource that is offline for - // it to be retrieved from the offline cache correctly. - // For example, if you have cached your main page as - // http://foobar.com/index.html, and you set this to - // http://www.foobar.com/index.html, the run link will - // not work. By default this value is automatically set to - // the URL of this page, so it does not need to be set - // manually unless you have unusual needs. - runLink: window.location.href, - - // runLinkTitle: String - // For advanced usage; most developers can ignore this. - // The text that will be inside of the link that a user - // can drag to their desktop to run this application offline. - // By default this is automatically set to "Run " plus your - // application's name. - runLinkTitle: "Run Application", - - // learnHowPath: String - // For advanced usage; most developers can ignore this. - // The path to a web page that has information on - // how to use this web app offline; defaults to - // src/off/ui-template/learnhow.html, relative to - // your Dojo installation. Make sure to set - // dojo.to.ui.customLearnHowPath to true if you want - // a custom Learn How page. - learnHowPath: dojo.moduleUrl("dojox", "off/resources/learnhow.html"), - - // customLearnHowPath: boolean - // For advanced usage; most developers can ignore this. - // Whether the developer is using their own custom page - // for the Learn How instructional page; defaults to false. - // Use in conjunction with dojox.off.ui.learnHowPath. - customLearnHowPath: false, - - htmlTemplatePath: dojo.moduleUrl("dojox", "off/resources/offline-widget.html").uri, - cssTemplatePath: dojo.moduleUrl("dojox", "off/resources/offline-widget.css").uri, - onlineImagePath: dojo.moduleUrl("dojox", "off/resources/greenball.png").uri, - offlineImagePath: dojo.moduleUrl("dojox", "off/resources/redball.png").uri, - rollerImagePath: dojo.moduleUrl("dojox", "off/resources/roller.gif").uri, - checkmarkImagePath: dojo.moduleUrl("dojox", "off/resources/checkmark.png").uri, - learnHowJSPath: dojo.moduleUrl("dojox", "off/resources/learnhow.js").uri, - - _initialized: false, - - onLoad: function(){ - // summary: - // A function that should be connected to allow your - // application to know when Dojo Offline, the page, and - // the Offline Widget are all initialized and ready to be - // used: - // - // dojo.connect(dojox.off.ui, "onLoad", someFunc) - }, - - _initialize: function(){ - //console.debug("dojox.off.ui._initialize"); - - // make sure our app name is correct - if(this._validateAppName(this.appName) == false){ - alert("You must set dojox.off.ui.appName; it can only contain " - + "letters, numbers, and spaces; right now it " - + "is incorrectly set to '" + dojox.off.ui.appName + "'"); - dojox.off.enabled = false; - return; - } - - // set our run link text to its default - this.runLinkText = "Run " + this.appName; - - // setup our event listeners for Dojo Offline events - // to update our UI - dojo.connect(dojox.off, "onNetwork", this, "_onNetwork"); - dojo.connect(dojox.off.sync, "onSync", this, "_onSync"); - - // cache our default UI resources - dojox.off.files.cache([ - this.htmlTemplatePath, - this.cssTemplatePath, - this.onlineImagePath, - this.offlineImagePath, - this.rollerImagePath, - this.checkmarkImagePath - ]); - - // embed the offline widget UI - if(this.autoEmbed){ - this._doAutoEmbed(); - } - }, - - _doAutoEmbed: function(){ - // fetch our HTML for the offline widget - - // dispatch the request - dojo.xhrGet({ - url: this.htmlTemplatePath, - handleAs: "text", - error: function(err){ - dojox.off.enabled = false; - err = err.message||err; - alert("Error loading the Dojo Offline Widget from " - + this.htmlTemplatePath + ": " + err); - }, - load: dojo.hitch(this, this._templateLoaded) - }); - }, - - _templateLoaded: function(data){ - //console.debug("dojox.off.ui._templateLoaded"); - // inline our HTML - var container = dojo.byId(this.autoEmbedID); - if(container){ container.innerHTML = data; } - - // fill out our image paths - this._initImages(); - - // update our network indicator status ball - this._updateNetIndicator(); - - // update our 'Learn How' text - this._initLearnHow(); - - this._initialized = true; - - // check offline cache settings - if(!dojox.off.hasOfflineCache){ - this._showNeedsOfflineCache(); - return; - } - - // check to see if we need a browser restart - // to be able to use this web app offline - if(dojox.off.hasOfflineCache && dojox.off.browserRestart){ - this._needsBrowserRestart(); - return; - }else{ - var browserRestart = dojo.byId("dot-widget-browser-restart"); - if(browserRestart){ browserRestart.style.display = "none"; } - } - - // update our sync UI - this._updateSyncUI(); - - // register our event listeners for our main buttons - this._initMainEvtHandlers(); - - // if offline functionality is disabled, disable everything - this._setOfflineEnabled(dojox.off.enabled); - - // update our UI based on the state of the network - this._onNetwork(dojox.off.isOnline ? "online" : "offline"); - - // try to go online - this._testNet(); - }, - - _testNet: function(){ - dojox.off.goOnline(dojo.hitch(this, function(isOnline){ - //console.debug("testNet callback, isOnline="+isOnline); - - // display our online/offline results - this._onNetwork(isOnline ? "online" : "offline"); - - // indicate that our default UI - // and Dojo Offline are now ready to - // be used - this.onLoad(); - })); - }, - - _updateNetIndicator: function(){ - var onlineImg = dojo.byId("dot-widget-network-indicator-online"); - var offlineImg = dojo.byId("dot-widget-network-indicator-offline"); - var titleText = dojo.byId("dot-widget-title-text"); - - if(onlineImg && offlineImg){ - if(dojox.off.isOnline == true){ - onlineImg.style.display = "inline"; - offlineImg.style.display = "none"; - }else{ - onlineImg.style.display = "none"; - offlineImg.style.display = "inline"; - } - } - - if(titleText){ - if(dojox.off.isOnline){ - titleText.innerHTML = "Online"; - }else{ - titleText.innerHTML = "Offline"; - } - } - }, - - _initLearnHow: function(){ - var learnHow = dojo.byId("dot-widget-learn-how-link"); - - if(!learnHow){ return; } - - if(!this.customLearnHowPath){ - // add parameters to URL so the Learn How page - // can customize itself and display itself - // correctly based on framework settings - var dojoPath = dojo.config.baseRelativePath; - this.learnHowPath += "?appName=" + encodeURIComponent(this.appName) - + "&hasOfflineCache=" + dojox.off.hasOfflineCache - + "&runLink=" + encodeURIComponent(this.runLink) - + "&runLinkText=" + encodeURIComponent(this.runLinkText) - + "&baseRelativePath=" + encodeURIComponent(dojoPath); - - // cache our Learn How JavaScript page and - // the HTML version with full query parameters - // so it is available offline without a cache miss - dojox.off.files.cache(this.learnHowJSPath); - dojox.off.files.cache(this.learnHowPath); - } - - learnHow.setAttribute("href", this.learnHowPath); - - var appName = dojo.byId("dot-widget-learn-how-app-name"); - - if(!appName){ return; } - - appName.innerHTML = ""; - appName.appendChild(document.createTextNode(this.appName)); - }, - - _validateAppName: function(appName){ - if(!appName){ return false; } - - return (/^[a-z0-9 ]*$/i.test(appName)); - }, - - _updateSyncUI: function(){ - var roller = dojo.byId("dot-roller"); - var checkmark = dojo.byId("dot-success-checkmark"); - var syncMessages = dojo.byId("dot-sync-messages"); - var details = dojo.byId("dot-sync-details"); - var cancel = dojo.byId("dot-sync-cancel"); - - if(dojox.off.sync.isSyncing){ - this._clearSyncMessage(); - - if(roller){ roller.style.display = "inline"; } - - if(checkmark){ checkmark.style.display = "none"; } - - if(syncMessages){ - dojo.removeClass(syncMessages, "dot-sync-error"); - } - - if(details){ details.style.display = "none"; } - - if(cancel){ cancel.style.display = "inline"; } - }else{ - if(roller){ roller.style.display = "none"; } - - if(cancel){ cancel.style.display = "none"; } - - if(syncMessages){ - dojo.removeClass(syncMessages, "dot-sync-error"); - } - } - }, - - _setSyncMessage: function(message){ - var syncMessage = dojo.byId("dot-sync-messages"); - if(syncMessage){ - // when used with Google Gears pre-release in Firefox/Mac OS X, - // the browser would crash when testing in Moxie - // if we set the message this way for some reason. - // Brad Neuberg, bkn3@columbia.edu - //syncMessage.innerHTML = message; - - while(syncMessage.firstChild){ - syncMessage.removeChild(syncMessage.firstChild); - } - syncMessage.appendChild(document.createTextNode(message)); - } - }, - - _clearSyncMessage: function(){ - this._setSyncMessage(""); - }, - - _initImages: function(){ - var onlineImg = dojo.byId("dot-widget-network-indicator-online"); - if(onlineImg){ - onlineImg.setAttribute("src", this.onlineImagePath); - } - - var offlineImg = dojo.byId("dot-widget-network-indicator-offline"); - if(offlineImg){ - offlineImg.setAttribute("src", this.offlineImagePath); - } - - var roller = dojo.byId("dot-roller"); - if(roller){ - roller.setAttribute("src", this.rollerImagePath); - } - - var checkmark = dojo.byId("dot-success-checkmark"); - if(checkmark){ - checkmark.setAttribute("src", this.checkmarkImagePath); - } - }, - - _showDetails: function(evt){ - // cancel the button's default behavior - evt.preventDefault(); - evt.stopPropagation(); - - if(!dojox.off.sync.details.length){ - return; - } - - // determine our HTML message to display - var html = ""; - html += "Sync Details"; - html += "

Sync Details

\n"; - html += "
    \n"; - for(var i = 0; i < dojox.off.sync.details.length; i++){ - html += "
  • "; - html += dojox.off.sync.details[i]; - html += "
  • "; - } - html += "
\n"; - html += "" - + "Close Window" - + "\n"; - html += ""; - - // open a popup window with this message - var windowParams = "height=400,width=600,resizable=true," - + "scrollbars=true,toolbar=no,menubar=no," - + "location=no,directories=no,dependent=yes"; - - var popup = window.open("", "SyncDetails", windowParams); - - if(!popup){ // aggressive popup blocker - alert("Please allow popup windows for this domain; can't display sync details window"); - return; - } - - popup.document.open(); - popup.document.write(html); - popup.document.close(); - - // put the focus on the popup window - if(popup.focus){ - popup.focus(); - } - }, - - _cancel: function(evt){ - // cancel the button's default behavior - evt.preventDefault(); - evt.stopPropagation(); - - dojox.off.sync.cancel(); - }, - - _needsBrowserRestart: function(){ - var browserRestart = dojo.byId("dot-widget-browser-restart"); - if(browserRestart){ - dojo.addClass(browserRestart, "dot-needs-browser-restart"); - } - - var appName = dojo.byId("dot-widget-browser-restart-app-name"); - if(appName){ - appName.innerHTML = ""; - appName.appendChild(document.createTextNode(this.appName)); - } - - var status = dojo.byId("dot-sync-status"); - if(status){ - status.style.display = "none"; - } - }, - - _showNeedsOfflineCache: function(){ - var widgetContainer = dojo.byId("dot-widget-container"); - if(widgetContainer){ - dojo.addClass(widgetContainer, "dot-needs-offline-cache"); - } - }, - - _hideNeedsOfflineCache: function(){ - var widgetContainer = dojo.byId("dot-widget-container"); - if(widgetContainer){ - dojo.removeClass(widgetContainer, "dot-needs-offline-cache"); - } - }, - - _initMainEvtHandlers: function(){ - var detailsButton = dojo.byId("dot-sync-details-button"); - if(detailsButton){ - dojo.connect(detailsButton, "onclick", this, this._showDetails); - } - var cancelButton = dojo.byId("dot-sync-cancel-button"); - if(cancelButton){ - dojo.connect(cancelButton, "onclick", this, this._cancel); - } - }, - - _setOfflineEnabled: function(enabled){ - var elems = []; - elems.push(dojo.byId("dot-sync-status")); - - for(var i = 0; i < elems.length; i++){ - if(elems[i]){ - elems[i].style.visibility = - (enabled ? "visible" : "hidden"); - } - } - }, - - _syncFinished: function(){ - this._updateSyncUI(); - - var checkmark = dojo.byId("dot-success-checkmark"); - var details = dojo.byId("dot-sync-details"); - - if(dojox.off.sync.successful == true){ - this._setSyncMessage("Sync Successful"); - if(checkmark){ checkmark.style.display = "inline"; } - }else if(dojox.off.sync.cancelled == true){ - this._setSyncMessage("Sync Cancelled"); - - if(checkmark){ checkmark.style.display = "none"; } - }else{ - this._setSyncMessage("Sync Error"); - - var messages = dojo.byId("dot-sync-messages"); - if(messages){ - dojo.addClass(messages, "dot-sync-error"); - } - - if(checkmark){ checkmark.style.display = "none"; } - } - - if(dojox.off.sync.details.length && details){ - details.style.display = "inline"; - } - }, - - _onFrameworkEvent: function(type, saveData){ - if(type == "save"){ - if(saveData.status == dojox.storage.FAILED && !saveData.isCoreSave){ - alert("Please increase the amount of local storage available " - + "to this application"); - if(dojox.storage.hasSettingsUI()){ - dojox.storage.showSettingsUI(); - } - - // FIXME: Be able to know if storage size has changed - // due to user configuration - } - }else if(type == "coreOperationFailed"){ - console.log("Application does not have permission to use Dojo Offline"); - - if(!this._userInformed){ - alert("This application will not work if Google Gears is not allowed to run"); - this._userInformed = true; - } - }else if(type == "offlineCacheInstalled"){ - // clear out the 'needs offline cache' info - this._hideNeedsOfflineCache(); - - // check to see if we need a browser restart - // to be able to use this web app offline - if(dojox.off.hasOfflineCache == true - && dojox.off.browserRestart == true){ - this._needsBrowserRestart(); - return; - }else{ - var browserRestart = dojo.byId("dot-widget-browser-restart"); - if(browserRestart){ - browserRestart.style.display = "none"; - } - } - - // update our sync UI - this._updateSyncUI(); - - // register our event listeners for our main buttons - this._initMainEvtHandlers(); - - // if offline is disabled, disable everything - this._setOfflineEnabled(dojox.off.enabled); - - // try to go online - this._testNet(); - } - }, - - _onSync: function(type){ - //console.debug("ui, onSync="+type); - switch(type){ - case "start": - this._updateSyncUI(); - break; - - case "refreshFiles": - this._setSyncMessage("Downloading UI..."); - break; - - case "upload": - this._setSyncMessage("Uploading new data..."); - break; - - case "download": - this._setSyncMessage("Downloading new data..."); - break; - - case "finished": - this._syncFinished(); - break; - - case "cancel": - this._setSyncMessage("Canceling Sync..."); - break; - - default: - dojo.warn("Programming error: " - + "Unknown sync type in dojox.off.ui: " + type); - break; - } - }, - - _onNetwork: function(type){ - // summary: - // Called when we go on- or off-line - // description: - // When we go online or offline, this method is called to update - // our UI. Default behavior is to update the Offline - // Widget UI and to attempt a synchronization. - // type: String - // "online" if we just moved online, and "offline" if we just - // moved offline. - - if(!this._initialized){ return; } - - // update UI - this._updateNetIndicator(); - - if(type == "offline"){ - this._setSyncMessage("You are working offline"); - - // clear old details - var details = dojo.byId("dot-sync-details"); - if(details){ details.style.display = "none"; } - - // if we fell offline during a sync, hide - // the sync info - this._updateSyncUI(); - }else{ // online - // synchronize, but pause for a few seconds - // so that the user can orient themselves - if(dojox.off.sync.autoSync){ - if(dojo.isAIR){ - window.setTimeout(function(){dojox.off.sync.synchronize();}, 1000); - }else{ - window.setTimeout(dojox._scopeName + ".off.sync.synchronize()", 1000); - } - } - } - } -}); - -// register ourselves for low-level framework events -dojo.connect(dojox.off, "onFrameworkEvent", dojox.off.ui, "_onFrameworkEvent"); - -// start our magic when the Dojo Offline framework is ready to go -dojo.connect(dojox.off, "onLoad", dojox.off.ui, dojox.off.ui._initialize); - -} -- cgit v1.2.3-54-g00ecf