diff --git a/README.md b/README.md
index 852e3a3..53df06a 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@ Extends and overrides a feature layer. This library allows you to extend esri.la
##offlineTilesEnabler
-Extends and overrides a tiled map service. Provides the ability to customize the extent used to cut the tiles. See the detailed description of basemap.prepareForOffline() in the "How To Use" section below to learn different options.
+Extends and overrides a tiled map service. Provides the ability to customize the extent used to cut the tiles. See the detailed description of basemap.prepareForOffline() in the "How To Use" section to learn different options.
* __Click [here](doc/offlinetilesenabler.md) to see the full API doc for `offlineTilesEnabler`__
@@ -57,6 +57,7 @@ Extends TileMapServiceLayer. You can display TPK files with this library.
* [Learn more about using the `tile` library](doc/howtousetiles.md)
* [Learn more about using the `edit` library](doc/howtouseeditlibrary.md)
* [Learn more about using the `tpk` library](doc/howtousetpklibrary.md)
+* [Learn more abuut using an application cache with this library](doc/howtouseappcache.md)
##Setup Instructions
@@ -68,7 +69,7 @@ Extends TileMapServiceLayer. You can display TPK files with this library.
##Samples
-* `appcache-features.html` - shows how to work with the application manifest and features.
+* `appcache-features.html` - shows how to work with the application manifest, tiles and features.
* `appcache-tiles.html` - shows how to work with the application manifest and map tiles.
* `attachments-editor.html` - demonstrates how to work with this library and feature attachments.
* `military-offline.html` - shows working with points, lines and polygons locally.
diff --git a/doc/howtouseappcache.md b/doc/howtouseappcache.md
new file mode 100644
index 0000000..ba71f7d
--- /dev/null
+++ b/doc/howtouseappcache.md
@@ -0,0 +1,68 @@
+Tips on using application cache
+===============================
+
+If you have a requirement to reload your application or restart the browser while offline then you will need to use the [application cache](http://appcachefacts.info/). Some developers also use application caches to speed up page reload performance. For example, Google uses an application cache when load their main web page.
+
+The application cache will allow you to store any file that is required for offline use. The list includes html files, JavaScript libraries, CSS and images. Any file that your application requires to run normally will have to be referenced in the application cache.
+
+Once an application is stored in the application cache it will be available the next time an application restarts.
+
+## Using AppCaches with your ArcGIS web app
+
+**Step 1** Make sure you are using an optimized build of the ArcGIS API for JavaScript. You can create an optimized build at [http://jso.arcgis.com/](http://jso.arcgis.com/). This will create a single file that contains all the necessary modules for your app. There are options to host the build via CDN or locally. Either approach will work.
+
+NOTE: You cannot use the regular CDN for the ArcGIS API for JavaScript because the URL contains a redirect. Redirects are not allowed in an application cache and it will fail to load.
+
+**Step 2** Create the application cache file. We have a [Grunt.js](http://gruntjs.com/) task included in the /samples directory to assist with this step. You will need to make some adjustments to the package.json file. It acts as the configuration file for the Grunt task.
+
+**Step 3** Reference the application cache file from within your application. Here's an example of the syntax:
+
+```html
+
+
+```
+
+**Step 4** Be sure to include and use the `/utils/appCacheManager.js` library as a module in your application. This will enable you to monitor what's going on in the application cache and capture specific events. Here is a psuedo code example of how to instantiate it:
+
+```js
+
+ appCacheManager = new AppCacheManager(true,true);
+ appCacheManager.on(appCacheManager.CACHE_EVENT,cacheEventHandler);
+ appCacheManager.on(appCacheManager.CACHE_ERROR,cacheErrorHandler);
+ appCacheManager.on(appCacheManager.CACHE_LOADED,cacheLoadedHandler);
+
+```
+
+In the `/samples` directory there are two examples, `appcache-features.html` and `appcache-tiles.html` that demonstrate how to use tiles, features and the appCacheManager with the application cache.
+
+###Configuring your web server
+Your web server must be able to serve up the MIME TYPE `TEXT/cache-manifest`. If this is missing there's a really good chance that the application cache file won't be served up to your app.
+
+### Clearing the application cache in a browser
+
+When you do testing with an application cache, any time you make a change to your application HTML, CSS or JS you will need to delete the existing application cache. Otherwise, any changes you make will not be reflected in the app.
+
+**Simply deleting your web cache the normal way won't clear an application cache!**
+
+In Chrome you can navigate to chrome://appcache-internals/ then select the appropriate cache and delete it. If you are testing on an Android device you can remotely debug from your laptop's Chrome instance.
+
+In Safari iPhone and iPad go to settings and select "Clear Cookies and Data."
+
+If you want to test on Firefox then try Tools > Options > Advanced > Network > Offline data > Clear Now. More info is available [here](https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache#Storage_location_and_clearing_the_offline_cache).
+
+As for IE, this library doesn't currently support any versions.
+
+### Where to place the file
+
+The application cache file can live anywhere in your web directory. It's common to see it to be placed in the root.
+
+###Support
+Most modern browsers support application cache including IE v10 and v11, Firefox v28+, Chrome v33+, Safari v7+, iOS Safari v3.2+, and Android browser 2.1+. For more detailed info refer to [caniuse.com](http://caniuse.com/#search=appcache).
+
+### References
+
+[Support for application cache](http://caniuse.com/#search=appcache)
+
+[Appcache Facts](http://appcachefacts.info/)
+
+[Using the application cache - Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache)
\ No newline at end of file
diff --git a/doc/howtousetiles.md b/doc/howtousetiles.md
index 4afa2ff..9a41c4e 100644
--- a/doc/howtousetiles.md
+++ b/doc/howtousetiles.md
@@ -3,9 +3,14 @@ How to use the tiles library
##`tiles` library
-
The `tiles` library allows a developer to extend a tiled layer with offline support.
+There are two approaches to using this set of libraries. The first approach is if you are using an ArcGIS.com Web Map, and the second approach is if you need to be able to restart or reload your application offline.
+
+## Approach 1 - ArcGIS.com Map
+
+Approach #1 is best for partial offline use cases and it uses the `offlineTilesEnabler.js` library. This approach will not allow you to reload or restart the application.
+
**Step 1** Configure paths for dojo loader to find the tiles and vendor modules (you need to set paths relative to the location of your html document), before loading ArcGIS JavaScript API
```html
@@ -19,7 +24,7 @@ The `tiles` library allows a developer to extend a tiled layer with offline supp
}
}
-
+
```
@@ -124,3 +129,72 @@ It calculates the geographic boundary of each of the tiles stored in the indexed
}
}
```
+
+## Approach #2 - Custom TileLayer
+
+This approach is best if you have requirements for restarting or reloading your application while offline. For this approach use the `OfflineTilesEnablerLayer.js` library. This library extends TileMapServiceLayer and you can use it with any Esri tiled basemap layer.
+
+
+**Step 1** Configure paths for dojo loader to find the tiles and vendor modules (you need to set paths relative to the location of your html document), before loading ArcGIS JavaScript API
+
+```html
+
+
+
+```
+
+**Step 2** Include the `tiles/offlineTilesEnabler` library in your app.
+
+```js
+ require([
+ "esri/map",
+ "tiles/OfflineTilesEnablerLayer"],
+ function(Map,OfflineTilesEnablerLayer)
+ {
+ ...
+ });
+```
+
+**Step 3** Create a new instance of `OfflineTilesEnablerLayer`. Note, when you instantiate the `Map` leave off the `basemap` property because we are adding a customer tile layer as our basemap. `OfflineTilesEnablerLayer` has three properties in the constructor. The first is the REST endpoint of the basemap you want to use, the second is the callback and the last is an optional parameter to preset the layer as online or offline. This will help with with drawing tiles correctly during offline restarts or reloads.
+
+```js
+ tileLayer = new OfflineTilesEnablerLayer("http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer",function(evt){
+ console.log("Tile Layer Loaded.");
+ },_isOnline);
+
+ var map = new Map("map",{
+ center: [-104.98,39.74], // long, lat
+ zoom: 8,
+ sliderStyle: "small"
+ });
+
+ map.addLayer(tileLayer);
+
+
+```
+
+All map events will continue to work normally. Although some methods that are typically available will now have to be accessed through the OfflineTilesEnablerLayer such as `getLevel()`, `getMaxZoom()`, and `getMinZoom()`.
+
+To get the current extent you will need to monitor the `zoom-end` and `pan-end` events like this:
+
+```js
+
+
+ map.on("zoom-end",function(evt){
+ _currentExtent = evt.extent;
+ });
+
+ map.on("pan-end",function(evt){
+ _currentExtent = evt.extent;
+ });
+
+```
\ No newline at end of file
diff --git a/doc/offlinetilesenabler.md b/doc/offlinetilesenabler.md
index d59d815..e417cc3 100644
--- a/doc/offlinetilesenabler.md
+++ b/doc/offlinetilesenabler.md
@@ -1,30 +1,25 @@
API Doc for offlineTilesEnabler
===============================
+There are two different libraries for taking tiles offline: offlineTilesEnabler.js and OfflineTilesEnablerLayer.js. The first one, offlineTilesEnabler.js, is for use with ArcGIS.com web maps and partial offline scenario. You won't be able to restart or reload your app when using this library.
+
+If you have a requirement to allow restarting or reloading then you should use OfflineTilesEnablerLayer.js. The OfflineTilesEnablerLayer.js library lets you create a custom basemap layer that extends TiledMapServiceLayer. To view the docs for this library scroll down on this page.
+
##offlineTilesEnabler
-Extends and overrides a tiled map service. Provides the ability to customize the extent used to cut the tiles. See the detailed description of basemap.prepareForOffline() in the "How To Use" section below to learn different options.
+Extends and overrides a tiled map service. For use with ArcGIS.com maps or partial-offline situations that don't require a browser restart or reload.
+
+Provides the ability to customize the extent used to cut the tiles. See the detailed description of basemap.prepareForOffline() in the "How To Use" section below to learn different options.
###Constructor
Constructor | Description
--- | ---
-`OfflineTilesEnabler()` | Creates an instance of the offlineTilesEnabler class. This library allows you to extend an ArcGISTiledMapServiceLayer with offline capability as well as manage the online/offline resynchronization process.
+`OfflineTilesEnabler()` | Creates an instance of the offlineTilesEnabler class. This library allows you to extend an ArcGISTiledMapServiceLayer with partial offline capability as well as manage the online/offline resynchronization process.
###Methods
Methods | Returns | Description
--- | --- | ---
`extend(layer, callback)`|`callback(boolean, string)` |Overrides an ArcGISTiledMapServiceLayer. Callback is called after indexedDb store is initialized and informs the application whether it is indexedDb is supported or not.
-
-###Properties
-Property | Description
---- | ---
-`layer.offline.proxyPath`| For CORS enabled servers this can be set to `null`. The default is to use the internal resource-proxy path: `libs/offline-editor-js/resource-proxy/proxy.php.` Don't forget to check your proxy configuration to allow connections for all possible services that you might be using. More information on using proxies with ArcGIS can be found here: [https://developers.arcgis.com/javascript/jshelp/ags_proxy.html](https://developers.arcgis.com/javascript/jshelp/ags_proxy.html).
-
-###ArcGISTiledMapServiceLayer Overrides
-
-Methods | Returns | Description
---- | --- | ---
-`getTileUrl(level, row, col)` | Url | Use the tile url's level, row and column. Retrieves tiles as requested by the ArcGIS API for JavaScript. If a tile is in cache it is returned. If it is not in cache then one is retrieved over the internet.
`goOffline()` | nothing | This method puts the layer in offline mode. When in offline mode, the layer will not fetch any tile from the remote server. It will look up the tiles in the indexed db database and display them in the layer. If the tile can't be found in the local database it will show up blank (even if there is actual connectivity). The pair of methods `goOffline()` and `goOnline() `allows the developer to manually control the behaviour of the layer. Used in conjunction with the offline dectection library, you can put the layer in the appropriate mode when the offline condition changes.
`goOnline()` | nothing | This method puts the layer in online mode. When in online mode, the layer will behave as regular layers, fetching all tiles from the remote server. If there is no internet connectivity the tiles may appear thanks to the browsers cache, but no attempt will be made to look up tiles in the local database.
`getLevelEstimation(extent,` `level, tileSize)` | {level, tileCount, sizeBytes} | Returns an object that contains the number of tiles that would need to be downloaded for the specified extent and zoom level, and the estimated byte size of such tiles. This method is useful to give the user an indication of the required time and space before launching the actual download operation. The byte size estimation is very rough.
@@ -38,3 +33,44 @@ Methods | Returns | Description
`estimateTileSize(callback)` | `callback(number)` | Retrieves one tile from a layer and then returns its size.
`prepareForOffline(` `minLevel, maxLevel, extent, ` `reportProgress)` | `callback(number)` | Retrieves tiles and stores them in the local cache. See the "How To Use" section below to learn more about customizing the use of this method.
+###Properties
+Property | Description
+--- | ---
+`layer.offline.proxyPath`| For CORS enabled servers this can be set to `null`. The default is to use the internal resource-proxy path: `libs/offline-editor-js/resource-proxy/proxy.php.` Don't forget to check your proxy configuration to allow connections for all possible services that you might be using. More information on using proxies with ArcGIS can be found here: [https://developers.arcgis.com/javascript/jshelp/ags_proxy.html](https://developers.arcgis.com/javascript/jshelp/ags_proxy.html).
+
+
+
+##OfflineTilesEnablerLayer
+Extends and overrides a tiled map service. This library creates a custom tiled map layer. It can be used in situations where a browser restart or reload is required.
+
+###Constructor
+Constructor | Description
+--- | ---
+`OfflineTilesEnablerLayer(url,callback,state)` | Creates an instance of the offlineTilesEnabler class. This library allows you to extend an ArcGISTiledMapServiceLayer with offline capability as well as manage the online/offline resynchronization process. Any Esri basemap REST endpoint should work. The state property is a boolean for specifying if the application is intializing the layer online (true) or offline (false). When you first load the map you should set this property to `true`.
+
+
+###Methods
+Methods | Returns | Description
+--- | --- | ---
+`goOffline()` | nothing | This method puts the layer in offline mode. When in offline mode, the layer will not fetch any tile from the remote server. It will look up the tiles in the indexed db database and display them in the layer. If the tile can't be found in the local database it will show up blank (even if there is actual connectivity). The pair of methods `goOffline()` and `goOnline() `allows the developer to manually control the behaviour of the layer. Used in conjunction with the offline dectection library, you can put the layer in the appropriate mode when the offline condition changes.
+`goOnline()` | nothing | This method puts the layer in online mode. When in online mode, the layer will behave as regular layers, fetching all tiles from the remote server. If there is no internet connectivity the tiles may appear thanks to the browsers cache, but no attempt will be made to look up tiles in the local database.
+`getLevelEstimation(extent,` `level, tileSize)` | {level, tileCount, sizeBytes} | Returns an object that contains the number of tiles that would need to be downloaded for the specified extent and zoom level, and the estimated byte size of such tiles. This method is useful to give the user an indication of the required time and space before launching the actual download operation. The byte size estimation is very rough.
+`getExtentBuffer(buffer,extent)`| Extent | Returns a new extent buffered by a given measurement that's based on map units. For example, if you are using mercator map projection then the buffer property would be in meters and the new extent would be returned in mercactor.
+`getTileUrlsByExtent(extent, level)` | Array | Returns an array of tile urls within a given map extent and zoom level.
+`deleteAllTiles(callback)` | `callback(boolean, errors)` | Clears the local cache of tiles.
+`getOfflineUsage(callback)` | `callback(size, error)` | Gets the size in bytes of the local tile cache.
+`getTilePolygons(callback)` | `callback(polygon, error)` | Gets polygons representing all cached tiles. This is helpful to give users a visual feedback of the current content of the tile cache.
+`saveToFile(filename, callback)` | `callback( boolean, error)` | Saves tile cache into a portable csv format.
+`loadFromFile(filename, callback)` | `callback( boolean, error)` | Reads a csv file into local tile cache.
+`estimateTileSize(callback)` | `callback(number)` | Retrieves one tile from a layer and then returns its size.
+`prepareForOffline(` `minLevel, maxLevel, extent, ` `reportProgress)` | `callback(number)` | Retrieves tiles and stores them in the local cache. See the "How To Use" section below to learn more about customizing the use of this method.
+`getMaxZoom(callback)` | `callback(number)` | Returns the maximum zoom level of the layer.
+`getMinZoom(callback)` | `callback(number)` | Returns the minimum zoom level of the layer.
+
+
+###Properties
+Property | Description
+--- | ---
+`layer.offline.proxyPath`| For CORS enabled servers this can be set to `null`. The default is to use the internal resource-proxy path: `libs/offline-editor-js/resource-proxy/proxy.php.` Don't forget to check your proxy configuration to allow connections for all possible services that you might be using. More information on using proxies with ArcGIS can be found here: [https://developers.arcgis.com/javascript/jshelp/ags_proxy.html](https://developers.arcgis.com/javascript/jshelp/ags_proxy.html).
+
+
diff --git a/lib/edit/offlineFeaturesManager.js b/lib/edit/offlineFeaturesManager.js
index 5e2019b..b652113 100644
--- a/lib/edit/offlineFeaturesManager.js
+++ b/lib/edit/offlineFeaturesManager.js
@@ -487,7 +487,7 @@ define([
*/
goOffline: function()
{
- console.log("going offline");
+ console.log("offlineFeatureManager going offline");
this._onlineStatus = this.OFFLINE;
},
@@ -498,7 +498,7 @@ define([
*/
goOnline: function(callback)
{
- console.log("going online");
+ console.log("offlineFeaturesManager going online");
this._onlineStatus = this.RECONNECTING;
this._replayStoredEdits(function(success,responses)
{
diff --git a/lib/edit/restartOfflineFeaturesManager.js b/lib/edit/restartOfflineFeaturesManager.js
new file mode 100644
index 0000000..420073b
--- /dev/null
+++ b/lib/edit/restartOfflineFeaturesManager.js
@@ -0,0 +1,58 @@
+/**
+ * Helper library for handling features during browser restarts or reloads.
+ */
+define(["esri/graphic"], function(Graphic) {
+ "use strict";
+
+ return {
+
+ /**
+ * Converts an array of graphics/features into JSON
+ * @param features
+ * @param updateEndEvent
+ * @param callback
+ */
+ convertGraphicLayerToJSON: function(features,updateEndEvent,callback){
+ var layerDefinition = {};
+ layerDefinition.objectIdFieldName = updateEndEvent.target.objectIdField;
+ layerDefinition.globalIdFieldName = updateEndEvent.target.globalIdField;
+ layerDefinition.geometryType = updateEndEvent.target.geometryType;
+ layerDefinition.spatialReference = updateEndEvent.target.spatialReference;
+ layerDefinition.fields = updateEndEvent.target.fields;
+
+ var length = features.length;
+ var jsonArray = [];
+ for(var i=0; i < length; i++){
+ var jsonGraphic = features[i].toJson();
+ jsonArray.push(jsonGraphic);
+ if(i == (length - 1)) {
+ var featureJSON = JSON.stringify(jsonArray);
+ var layerDefJSON = JSON.stringify(layerDefinition);
+ callback(featureJSON,layerDefJSON);
+ break;
+ }
+ }
+ },
+
+ /**
+ * Create a featureDefinition
+ * @param featureLayer
+ * @param featuresArr
+ * @param geometryType
+ * @param callback
+ */
+ getFeatureDefinition: function(/* Object */ featureLayer,/* Array */ featuresArr,/* String */ geometryType,callback){
+
+ var featureDefinition = {
+ "layerDefinition":featureLayer,
+ "featureSet":{
+ "features": featuresArr,
+ "geometryType": geometryType
+ }
+
+ }
+
+ callback(featureDefinition);
+ }
+ }
+})
\ No newline at end of file
diff --git a/lib/resource-proxy/proxy.config b/lib/resource-proxy/proxy.config
index f79c618..0ec2139 100644
--- a/lib/resource-proxy/proxy.config
+++ b/lib/resource-proxy/proxy.config
@@ -21,6 +21,7 @@
),
)
+
diff --git a/lib/tiles/OfflineTilesEnablerLayer.js b/lib/tiles/OfflineTilesEnablerLayer.js
new file mode 100644
index 0000000..fbaa720
--- /dev/null
+++ b/lib/tiles/OfflineTilesEnablerLayer.js
@@ -0,0 +1,699 @@
+define([
+ "dojo/query",
+ "dojo/request",
+ "dojo/_base/declare",
+ "tiles/base64utils",
+ "tiles/TilesStore",
+ "tiles/tilingScheme",
+ "tiles/FileSaver",
+ "esri/layers/LOD",
+ "esri/geometry/Point",
+ "esri/geometry/Extent",
+ "esri/layers/TileInfo",
+ "esri/SpatialReference",
+ "esri/layers/TiledMapServiceLayer"
+], function(query, request, declare,Base64Utils,TilesStore,TilingScheme,
+ FileSaver,LOD,Point,Extent,TileInfo,SpatialReference,TiledMapServerLayer)
+{
+ "use strict";
+ return declare("OfflineTileEnablerLayer",[TiledMapServerLayer],{
+
+ tileInfo: null,
+ _imageType: "",
+ _level: null, //current zoom level
+ _minZoom: null,
+ _maxZoom: null,
+
+ constructor:function(url,callback,state){
+
+ if(this._isLocalStorage() === false){
+ alert("OfflineTiles Library not supported on this browser.");
+ callback(false);
+ }
+
+ //For calculating minZoom and maxZoom
+ Array.prototype.sortNumber = function(){return this.sort(function(a,b){return a - b})};
+
+ this._self = this;
+ this._lastTileUrl = "";
+ this._imageType = "";
+
+ /* we add some methods to the layer object */
+ /* we don't want to extend the tiled layer class, as it is a capability that we want to add only to one instance */
+ /* we also add some additional attributes inside an "offline" object */
+
+ this._getTileUrl = this.getTileUrl;
+
+ var isOnline = true;
+ if(typeof state != "undefined" || state != null){
+ isOnline = state; console.log("STATE IS: " + state)
+ }
+
+ this.offline = {
+ online: isOnline,
+ store: new TilesStore(),
+ proxyPath: "../lib/resource-proxy/proxy.php"
+ };
+
+ if( /*false &&*/ this.offline.store.isSupported() )
+ {
+ this.offline.store.init(function(success){
+ if(success){
+ this._getTileInfoPrivate(url,function(result){
+
+ // Store the layerInfo locally so we have it when browser restarts or is reloaded.
+ // We need this info in order to properly rebuild the layer.
+ if(localStorage.__offlineTileInfo == undefined && result != false){
+ localStorage.__offlineTileInfo = result;
+ }
+
+ // If library is offline then attempt to get layerInfo from localStorage.
+ if(this.offline.online == false && result == false && localStorage.__offlineTileInfo != undefined){
+ result = localStorage.__offlineTileInfo;
+ }
+ else if(this.offline.online == false && result == false && localStorage.__offlineTileInfo == undefined){
+ alert("There was a problem retrieving tiled map info in OfflineTilesEnablerLayer.");
+ }
+
+ this.parseGetTileInfo(result,function(tileResult){
+ this.layerInfos = tileResult.resultObj.layers;
+ this.minScale = tileResult.resultObj.minScale;
+ this.maxScale = tileResult.resultObj.maxScale;
+ this.tileInfo = tileResult.tileInfo;
+ this._imageType = this.tileInfo.format.toLowerCase();
+ this.fullExtent = tileResult.fullExtent;
+ this.spatialReference = this.tileInfo.spatialReference;
+ this.initialExtent = tileResult.initExtent;
+ this.loaded = true;
+ this.onLoad(this);
+ callback(true);
+ }.bind(this._self));
+ }.bind(this._self))
+ }
+ }.bind(this._self));
+ }
+ else
+ {
+ return callback(false, "indexedDB not supported");
+ }
+ },
+
+ /**
+ * Internal method that overrides the getTileUrl() method.
+ * If application is offline then tiles are written to IndexedDB.
+ * Retrieves tiles as requested by the ArcGIS API for JavaScript.
+ * If a tile is in cache it is returned.
+ * If it is not in cache then one is retrieved over the internet.
+ * @param level
+ * @param row
+ * @param col
+ * @returns {String} URL
+ */
+ getTileUrl: function(level,row,col)
+ {
+ console.assert(!isNaN(level) && !isNaN(row) && !isNaN(col), "bad tile requested");
+ console.log("looking for tile",level,row,col);
+
+ this._level = level;
+
+ var url = this.url + "/tile/" + level + "/" + row + "/" + col;
+ console.log("LIBRARY ONLINE " + this.offline.online)
+ if( this.offline.online )
+ {
+ console.log("fetching url online: ", url);
+ this._lastTileUrl = url;
+ return url;
+ }
+
+ url = url.split("?")[0];
+
+ /* temporary URL returned immediately, as we haven't retrieved the image from the indexeddb yet */
+ var tileid = "void:/"+level+"/"+row+"/"+col;
+
+ this.offline.store.retrieve(url, function(success, offlineTile)
+ { console.log("TILE RETURN " + success + ", " + offlineTile)
+ /* when the .getTileUrl() callback is triggered we replace the temporary URL originally returned by the data:image url */
+ // search for the img with src="void:"+level+"-"+row+"-"+col and replace with actual url
+ var img = query("img[src="+tileid+"]")[0];
+ var imgURL;
+
+ console.assert(img !== "undefined", "undefined image detected");
+
+ if( success )
+ {
+ img.style.borderColor = "blue";
+ console.log("found tile offline", url);
+ imgURL = "data:image/" + this._imageType +";base64," + offlineTile.img;
+ }
+ else
+ {
+ img.style.borderColor = "green";
+ console.log("tile is not in the offline store", url);
+ imgURL = "data:image/png;base64,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pmk0TROPj48Hn3l4eIimaSJN06O3A4NJwDMxm82ibdtXo4D5fB6r1Sp+//4dz8/Pw5H+6ekpdrtdJEkS8/n8S/9f713ie3vaceo9x557QAB451Sgfyin34HKshweunk5HzAej2MymXz5+f9nbjJyI9L39Wu5XP55+XQZ39uxR4Z3u90wSXjqEV0wAjhjx47oaZq63Me/ZhIQBAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAAbAJQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAvqe/BwCeKjUweoA8pQAAAABJRU5ErkJggg==";
+ }
+ // when we return a nonexistent url to the image, the TiledMapServiceLayer::_tileErrorHandler() method
+ // sets img visibility to 'hidden', so we need to show the image back once we have put the data:image
+ img.style.visibility = "visible";
+ img.src = imgURL;
+ return ""; /* this result goes nowhere, seriously */
+ }.bind(this));
+
+ return tileid;
+ },
+
+ /**
+ * Utility method to get the basemap layer reference
+ * @param map
+ * @returns {Number} layerId
+ */
+ getBasemapLayer: function(map)
+ {
+ var layerId = map.layerIds[0];
+ return map.getLayer(layerId);
+ },
+
+ /**
+ * Returns an object that contains the number of tiles that would need to be downloaded
+ * for the specified extent and zoom level, and the estimated byte size of such tiles.
+ * This method is useful to give the user an indication of the required time and space
+ * before launching the actual download operation. The byte size estimation is very rough.
+ * @param extent
+ * @param level
+ * @param tileSize
+ * @returns {{level: *, tileCount: Number, sizeBytes: number}}
+ */
+ getLevelEstimation: function(extent, level, tileSize)
+ {
+ var tilingScheme = new TilingScheme(this);
+ var cellIds = tilingScheme.getAllCellIdsInExtent(extent,level);
+
+ var levelEstimation = {
+ level: level,
+ tileCount: cellIds.length,
+ sizeBytes: cellIds.length * tileSize
+ };
+
+ return levelEstimation;
+ },
+
+ /**
+ * Returns the current zoom level
+ * @returns {number}
+ */
+ getLevel: function(){
+ return this._level;
+ },
+
+ /**
+ * Returns the maximum zoom level for this layer
+ * @param callback number
+ */
+ getMaxZoom: function(callback){
+
+ if(this._maxZoom == null){
+ var lods = this.tileInfo.lods;
+ var length = this.tileInfo.lods.length;
+ var tempArr = [];
+ for(var i=0; i < length; i++){
+ tempArr.push(lods[i].level);
+ if(i == length -1){
+ tempArr.sortNumber();
+ this._maxZoom = tempArr[i];
+ callback(tempArr[i]);
+ }
+ }
+ }
+ else{
+ callback(this._maxZoom);
+ }
+
+ },
+
+ /**
+ * Returns the minimum zoom level for this layer
+ * @param callback number
+ */
+ getMinZoom: function(callback){
+
+ if(this._minZoom == null){
+ var lods = this.tileInfo.lods;
+ var length = this.tileInfo.lods.length;
+ var tempArr = [];
+ for(var i=0; i < length; i++){
+ tempArr.push(lods[i].level);
+ if(i == length -1){
+ tempArr.sortNumber();
+ this._minZoom = tempArr[0];
+ callback(tempArr[0]);
+ }
+ }
+ }
+ else{
+ callback(this._minZoom);
+ }
+ },
+
+ /**
+ * Retrieves tiles and stores them in the local cache.
+ * @param minLevel
+ * @param maxLevel
+ * @param extent
+ * @param reportProgress
+ */
+ prepareForOffline : function(minLevel, maxLevel, extent, reportProgress)
+ {
+ /* create list of tiles to store */
+ var tilingScheme = new TilingScheme(this);
+ var cells = [];
+ var level;
+
+ for(level=minLevel; level<=maxLevel; level++)
+ {
+ var level_cell_ids = tilingScheme.getAllCellIdsInExtent(extent,level);
+
+ level_cell_ids.forEach(function(cell_id)
+ {
+ cells.push({ level: level, row: cell_id[1], col: cell_id[0]});
+ });
+
+ // if the number of requested tiles is excessive, we just stop
+ if( cells.length > 5000 && level !== maxLevel)
+ {
+ console.log("enough is enough!");
+ break;
+ }
+ }
+
+ /* launch tile download */
+ this._doNextTile(0, cells, reportProgress);
+ },
+
+ /**
+ * This method puts the layer in offline mode. When in offline mode,
+ * the layer will not fetch any tile from the remote server. It
+ * will look up the tiles in the indexed db database and display them in the
+ * If the tile can't be found in the local database it will show up blank
+ * (even if there is actual connectivity). The pair of methods goOffline() and
+ * goOnline()allows the developer to manually control the behaviour of the
+ * Used in conjunction with the offline dectection library, you can put the layer in
+ * the appropriate mode when the offline condition changes.
+ */
+ goOffline : function()
+ {
+ this.offline.online = false;
+ },
+
+ /**
+ * This method puts the layer in online mode. When in online mode, the layer will
+ * behave as regular layers, fetching all tiles from the remote server.
+ * If there is no internet connectivity the tiles may appear thanks to the browsers cache,
+ * but no attempt will be made to look up tiles in the local database.
+ */
+ goOnline : function()
+ {
+ this.offline.online = true;
+ this.refresh();
+ },
+
+ /**
+ * Determines if application is online or offline
+ * @returns {boolean}
+ */
+ isOnline : function()
+ {
+ return this.offline.online;
+ },
+
+ /**
+ * Clears the local cache of tiles.
+ * @param callback callback(boolean, errors)
+ */
+ deleteAllTiles : function(callback) // callback(success) or callback(false, error)
+ {
+ var store = this.offline.store;
+ store.deleteAll(callback);
+ },
+
+ /**
+ * Gets the size in bytes of the local tile cache.
+ * @param callback callback(size, error)
+ */
+ getOfflineUsage : function(callback) // callback({size: <>, tileCount: <>}) or callback(null,error)
+ {
+ var store = this.offline.store;
+ store.usedSpace(callback);
+ },
+
+ /**
+ * Gets polygons representing all cached cell ids within a particular
+ * zoom level and bounded by an extent.
+ * @param callback callback(polygon, error)
+ */
+ getTilePolygons : function(callback) // callback(Polygon polygon) or callback(null, error)
+ {
+ var store = this.offline.store;
+ var tilingScheme = new TilingScheme(this);
+ store.getAllTiles(function(url,img,err)
+ {
+ if(url)
+ {
+ var components = url.split("/");
+ var level = parseInt(components[ components.length - 3],10);
+ var col = parseInt(components[ components.length - 2],10);
+ var row = parseInt(components[ components.length - 1],10);
+ var cellId = [row,col];
+ var polygon = tilingScheme.getCellPolygonFromCellId(cellId, level);
+ //if( level == 15)
+ callback(polygon);
+ }
+ else
+ {
+ callback(null,err);
+ }
+ });
+ },
+
+ /**
+ * Saves tile cache into a portable csv format.
+ * @param fileName
+ * @param callback callback( boolean, error)
+ */
+ saveToFile : function(fileName, callback) // callback(success, msg)
+ {
+ var store = this.offline.store;
+ var csv = [];
+
+ csv.push("url,img");
+ store.getAllTiles(function(url,img,evt)
+ {
+ if(evt==="end")
+ {
+ var blob = new Blob([ csv.join("\r\n") ], {type:"text/plain;charset=utf-8"});
+ var saver = FileSaver.saveAs(blob, fileName);
+
+ if( saver.readyState === saver.DONE )
+ {
+ if( saver.error )
+ {
+ return callback(false,"Error saving file " + fileName);
+ }
+ return callback(true, "Saved " + (csv.length-1) + " tiles (" + Math.floor(blob.size / 1024 / 1024 * 100) / 100 + " Mb) into " + fileName);
+ }
+ saver.onerror = function() {
+ callback(false,"Error saving file " + fileName);
+ };
+ saver.onwriteend = function()
+ {
+ callback(true, "Saved " + (csv.length-1) + " tiles (" + Math.floor(blob.size / 1024 / 1024 * 100) / 100 + " Mb) into " + fileName);
+ };
+ }
+ else
+ {
+ csv.push(url+","+img);
+ }
+ });
+ },
+
+ /**
+ * Reads a csv file into local tile cache.
+ * @param file
+ * @param callback callback( boolean, error)
+ */
+ loadFromFile : function(file, callback) // callback(success,msg)
+ {
+ console.log("reading",file);
+
+ var store = this.offline.store;
+ var i;
+
+ if (window.File && window.FileReader && window.FileList && window.Blob)
+ {
+ // Great success! All the File APIs are supported.
+ var reader = new FileReader();
+ reader.onload = function(evt)
+ {
+ var csvContent = evt.target.result;
+ var tiles = csvContent.split("\r\n");
+ var tileCount = 0;
+ var pair, tile;
+
+ if(tiles[0] !== "url,img")
+ {
+ return callback(false, "File " + file.name + " doesn't contain tiles that can be loaded");
+ }
+
+ for(i=1; i/dojo/dojo.js",
+ "<%= pkg.optimizedApiURL %>/dojo/nls/dojo_en-us.js",
+ "<%= pkg.optimizedApiURL %>/dojo/selector/acme.js",
"#",
+ "<%= pkg.arcGISBaseURL %>/js/esri/dijit/images/popup-sprite.png",
+ "<%= pkg.arcGISBaseURL %>/js/esri/dijit/images/attribute_inspector_sprite.png",
"<%= pkg.arcGISBaseURL %>/js/dojo/dojox/gfx/svg.js",
"<%= pkg.arcGISBaseURL %>/js/dojo/dojo/resources/blank.gif",
"<%= pkg.arcGISBaseURL %>/js/esri/dijit/images/ajax-loader.gif",
"<%= pkg.arcGISBaseURL %>/js/esri/images/map/logo-sm.png",
"<%= pkg.arcGISBaseURL %>/js/esri/images/map/logo-med.png",
"<%= pkg.arcGISBaseURL %>/js/esri/css/esri.css",
+ "<%= pkg.arcGISBaseURL %>/js/dojo/dijit/themes/claro/claro.css",
"<%= pkg.arcGISBaseURL %>/js/esri/nls/jsapi_en-us.js",
"#",
"//services.arcgisonline.com/ArcGIS/rest/info?f=json",
@@ -42,7 +47,7 @@ module.exports = function(grunt) {
"# required for web maps",
"<%= pkg.arcGISBaseURL %>/js/esri/dijit/images/ajax-loader.gif",
"#",
- "# required custom libs",
+ "# required local html",
"# /xyz/style.css",
"# /img/1.png"],
network: [
@@ -56,18 +61,19 @@ module.exports = function(grunt) {
},
src: [
"*.html",
- /*"js/*.min.js",*/
- "samples/images/*.png",
- "vendor/IndexedDBShim/dist/*.min.js",
- "vendor/offline/offline.min.js",
- "lib/tiles/*.js",
- "lib/tiles/*.png",
- "lib/tiles/*.psd",
- "utils/*.js"
- /*
- "images/*",
- "css/*.css"
- */
+ "../samples/images/*.png",
+ "../samples/css/*.css",
+ "../vendor/IndexedDBShim/dist/*.js",
+ "../vendor/offline/offline.min.js",
+ "../lib/tiles/*.js",
+ "../lib/tiles/*.png",
+ "../lib/tiles/*.psd",
+ "../lib/edit/*.js",
+ "../utils/*.js"
+ /*
+ "images/*",
+ "css/*.css"
+ */
],
dest: "<%= pkg.manifestName %>"
}
diff --git a/samples/appcache-features.appcache b/samples/appcache-features.appcache
index daf4929..e5d5362 100644
--- a/samples/appcache-features.appcache
+++ b/samples/appcache-features.appcache
@@ -1,6 +1,6 @@
CACHE MANIFEST
# This manifest was generated by grunt-manifest HTML5 Cache Manifest Generator
-# Time: Mon May 19 2014 13:37:55 GMT-0600 (MDT)
+# Time: Wed Jun 11 2014 13:42:14 GMT-0600 (MDT)
CACHE:
# manifest-generator, version: 0.0.1
@@ -9,14 +9,19 @@ CACHE:
appcache-features.html
#
# ArcGIS API for JavaScript files
-http://js.arcgis.com/o/agup_hack4co/appcache2/dojo/dojo.js
+http://js.arcgis.com/o/agup_hack4co/appcacheFeatures/dojo/dojo.js
+http://js.arcgis.com/o/agup_hack4co/appcacheFeatures/dojo/nls/dojo_en-us.js
+http://js.arcgis.com/o/agup_hack4co/appcacheFeatures/dojo/selector/acme.js
#
+http://js.arcgis.com/3.9/js/esri/dijit/images/popup-sprite.png
+http://js.arcgis.com/3.9/js/esri/dijit/images/attribute_inspector_sprite.png
http://js.arcgis.com/3.9/js/dojo/dojox/gfx/svg.js
http://js.arcgis.com/3.9/js/dojo/dojo/resources/blank.gif
http://js.arcgis.com/3.9/js/esri/dijit/images/ajax-loader.gif
http://js.arcgis.com/3.9/js/esri/images/map/logo-sm.png
http://js.arcgis.com/3.9/js/esri/images/map/logo-med.png
http://js.arcgis.com/3.9/js/esri/css/esri.css
+http://js.arcgis.com/3.9/js/dojo/dijit/themes/claro/claro.css
http://js.arcgis.com/3.9/js/esri/nls/jsapi_en-us.js
#
//services.arcgisonline.com/ArcGIS/rest/info?f=json
@@ -26,7 +31,7 @@ http://js.arcgis.com/3.9/js/esri/nls/jsapi_en-us.js
# required for web maps
http://js.arcgis.com/3.9/js/esri/dijit/images/ajax-loader.gif
#
-# required custom libs
+# required local html
# /xyz/style.css
# /img/1.png
appcache-features.html
@@ -36,6 +41,27 @@ attachments-editor.html
military-offline.html
service-inspector.html
tiles-indexed-db.html
+tpk-layer.html
+../samples/images/blue-pin.png
+../samples/images/red-pin.png
+../samples/css/modular-popup.css
+../vendor/IndexedDBShim/dist/IndexedDBShim.js
+../vendor/IndexedDBShim/dist/IndexedDBShim.min.js
+../vendor/offline/offline.min.js
+../lib/tiles/FileSaver.js
+../lib/tiles/OfflineTilesEnablerLayer.js
+../lib/tiles/TilesStore.js
+../lib/tiles/base64utils.js
+../lib/tiles/offlineTilesEnabler.js
+../lib/tiles/tilingScheme.js
+../lib/tiles/notile.png
+../lib/tiles/notile.psd
+../lib/edit/attachmentsStore.js
+../lib/edit/editsStore.js
+../lib/edit/offlineFeaturesManager.js
+../lib/edit/restartOfflineFeaturesManager.js
+../utils/appCacheManager.js
+../utils/debouncer.js
NETWORK:
*
diff --git a/samples/appcache-features.html b/samples/appcache-features.html
index 4711e9c..02a9439 100644
--- a/samples/appcache-features.html
+++ b/samples/appcache-features.html
@@ -1,31 +1,17 @@
+
-
- Cache Features Sample
-
-
+
+
+ AppCache Tiles and Features
+
+
+
-
-
+
+
+
+
+
+