The offline-edit-advanced-min.js library is for working with ArcGIS JS API points, lines, polygons and attachments in intermittent and full offline use cases.
94 | This library has limited support for attachments.
95 |
The offline-tiles-basic-min.js library is for use with ArcGIS.com web maps and partial/intermittently offline use cases.
120 | You won't be able to restart or reload your app when using this library offline.
121 |
The offline-tiles-advanced-min.js library is for use with tiled map services in partial or fully offline use cases.
139 | If you have a requirement to reload or restart your app while offline you should use this library.
140 |
The offline-tpk-min.js library is for working with TPK files in partial or fully offline use cases.
158 | TPK files are binary tile image packages. They can be used stand-alone or alongside tiled base maps.
159 |
--------------------------------------------------------------------------------
/demo/images/appcachefeatures-demo-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Esri/offline-editor-js/f4d324b01ab5d3912088509c001d7dbbde4746ae/demo/images/appcachefeatures-demo-thumb.png
--------------------------------------------------------------------------------
/demo/images/appcachetiles-demo-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Esri/offline-editor-js/f4d324b01ab5d3912088509c001d7dbbde4746ae/demo/images/appcachetiles-demo-thumb.png
--------------------------------------------------------------------------------
/demo/images/attachments-demo-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Esri/offline-editor-js/f4d324b01ab5d3912088509c001d7dbbde4746ae/demo/images/attachments-demo-thumb.png
--------------------------------------------------------------------------------
/demo/images/cop-demo-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Esri/offline-editor-js/f4d324b01ab5d3912088509c001d7dbbde4746ae/demo/images/cop-demo-thumb.png
--------------------------------------------------------------------------------
/demo/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Esri/offline-editor-js/f4d324b01ab5d3912088509c001d7dbbde4746ae/demo/images/favicon.ico
--------------------------------------------------------------------------------
/demo/images/offline_arch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Esri/offline-editor-js/f4d324b01ab5d3912088509c001d7dbbde4746ae/demo/images/offline_arch.png
--------------------------------------------------------------------------------
/demo/images/simple-edit-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Esri/offline-editor-js/f4d324b01ab5d3912088509c001d7dbbde4746ae/demo/images/simple-edit-thumb.png
--------------------------------------------------------------------------------
/demo/images/tiles-demo-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Esri/offline-editor-js/f4d324b01ab5d3912088509c001d7dbbde4746ae/demo/images/tiles-demo-thumb.png
--------------------------------------------------------------------------------
/demo/images/tpk-demo-thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Esri/offline-editor-js/f4d324b01ab5d3912088509c001d7dbbde4746ae/demo/images/tpk-demo-thumb.png
--------------------------------------------------------------------------------
/doc/attachments.md:
--------------------------------------------------------------------------------
1 | # Attachment Support
2 | The __offline-edit-advanced-min.js__ has support for attachments in offline mode. See [attachments-editor.html](../samples/attachments-editor.html) sample.
3 |
4 | ## What you can do:
5 | While your application is in `OFFLINE` mode, you can:
6 |
7 | * add attachments to any feature, either a feature that already exists in the server or a newly added feature.
8 | * delete attachments from features if you have pre-cached the attachments or if you have added a feature while offline you can delete it from the local database.
9 | * query for attachments of a particular feature. It will only return attachments that have been added while offline.
10 | * view the attached files (see __limitations__ below)
11 | * when the app goes to `ONLINE` mode, all attachments are sent back to the server and removed from the local database.
12 |
13 | ## How you do use it:
14 | You can either use the ArcGIS FeatureLayer API _(esri.layers.FeatureLayer)_ directly or use the [AttachmentEditor](https://developers.arcgis.com/javascript/jsapi/attachmenteditor-amd.html) widget that supports feature attachment editing. Both approaches work well, and the code you write works the same either if you are on `ONLINE` or `OFFLINE` modes.
15 |
16 | The only differences in your code are:
17 |
18 | * create an OfflineEditAdvanced instance that is enabled for attachment support. Make sure you initialize the attachments database:
19 |
20 | var offlineEdit = new O.esri.Edit.OfflineEditAdvanced();
21 | offlineEdit.initAttachments(function(success, error){ . . . });
22 |
23 | * extend your featureLayers with offline editing functionality:
24 |
25 | offlineEdit.extend(featureLayer, function(success, error)
26 | {
27 | console.log("layer extended", success? "success" : "failed");
28 | });
29 |
30 | You can also modified the database's name and object store name. This functionality is typically used for advanced
31 | users that have a requirement to run multiple databases:
32 |
33 | var offlineEdit = new O.esri.Edit.OfflineEditAdvanced();
34 | offlineEdit.ATTACHMENTS_DB_NAME = "attachment-store-two";
35 | offlineEdit.ATTACHMENTS_DB_OBJECTSTORE_NAME = "attachments-two";
36 |
37 | offlineEdit.initAttachments(function(success, error){ . . . });
38 |
39 | ### Using the FeatureLayer API
40 | The FeatureLayer API for handling attachments consists primarily of four methods. In general you should let `OfflineEditAdvanced`
41 | handle interactions with attachments and it's not recommended to interact with the attachments database directly.
42 |
43 | * `layer.queryAttachmentInfos(objectId,callback,errback)` [doc](https://developers.arcgis.com/javascript/jsapi/featurelayer.html#queryattachmentinfos)
44 | * `layer.addAttachment(objectId, formNode, callback, errback)` [doc](https://developers.arcgis.com/javascript/jsapi/featurelayer.html#addattachment)
45 | * `layer.updateAttachment(objectId, attachmentId, formNode, callback, errback)` - as of April 2015 the ArcGIS API for JavaScript document has this functionality but it's not documented. That should hopefully be fixed in the next release of the JS API.
46 | * `layer.deleteAttachments(objectId, attachmentIds, callback, errback)` [doc](https://developers.arcgis.com/javascript/jsapi/featurelayer.html#deleteattachments)
47 |
48 | They work the same both in ONLINE and OFFLINE mode. In OFFLINE mode, attachments will be kept in the local database (indexeddb) and sent back to the server when you call `offlineEdit.goOnline()`
49 |
50 | ## Getting database usage
51 | Once a feature layer is extended you can find out how big the database and how many attachments are stored by using the following pattern:
52 |
53 | layer.getAttachmentsUsage(function(usage, error) {
54 | console.log("Size: " + usage.sizeBytes + ", attachmentCount: " + usage.attachmentCount);
55 | });
56 |
57 | ## Resetting the database
58 | Under certain circumstances you may want to force the database to delete everything.
59 |
60 | layer.resetAttachmentsDatabase(function(result, error) {
61 | console.log("Reset succes: " + result); // result is a boolean
62 | });
63 |
64 | ### Using the AttachmentEditor widget
65 | The [AttachmentEditor](https://developers.arcgis.com/javascript/jsapi/attachmenteditor-amd.html) is not very fancy, but it's easy to work with:
66 |
67 | map.infoWindow.setContent("");
68 | map.infoWindow.resize(350,200);
69 | var attachmentEditor = new AttachmentEditor({}, dom.byId("content"));
70 | attachmentEditor.startup();
71 |
72 | featureLayer.on("click", function(evt)
73 | {
74 | var event = evt;
75 | var objectId = evt.graphic.attributes[featureLayer.objectIdField];
76 | map.infoWindow.setTitle(objectId);
77 | attachmentEditor.showAttachments(event.graphic,featureLayer);
78 | map.infoWindow.show(evt.screenPoint, map.getInfoWindowAnchor(evt.screenPoint));
79 | });
80 |
81 | The widget internally uses the FeatureLayer API, and it works well in OFFLINE mode.
82 |
83 |
84 | ## Limitations
85 | Attachment support in OFFLINE mode has some limitations:
86 |
87 | * While in OFFLINE mode, features in a featureLayer don't know whether they have any attachments on the server or any other information about attachments unless you specifically build out that functionality. Therefore `queryAttachmentInfos()` and `deleteAttachments()` won't take their respective attachments into account. Calling `queryAttachmentInfos()` will only return locally stored attachments and `deleteAttachments()` can also only remove local attachments.
--------------------------------------------------------------------------------
/doc/dependencies.md:
--------------------------------------------------------------------------------
1 | # Technical Dependencies
2 |
3 | The offline-editor-js projects includes but is not limited to the following dependencies:
4 |
5 | * indexedDB. Storage limits for indexedDB are not necessarily consistent across browsers. Here is a Mozilla [document](https://developer.mozilla.org/en-US/docs/IndexedDB#Storage_limits) discussing limits across different browsers.
6 | * Advanced users of the library should be aware that JavaScript stores some strings as UTF-16. More information can be found in this Mozilla [article](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length).
7 | * If a user completely flushes their browser cache all queued edits, tiles as well as anything stored in local storage, IndexedDB, SQLite or even the appcache will most likely be lost.
8 | * Data stored by the library should persist if the browser is shutdown and restarted. However, this does not mean that your application will be returned to its correct state. A client web application's state has to be programmatically managed. This includes the state of items including but not limited to feature layers within your application.
9 | * Browser support for all the functionality in this library isn't gauranteed, of course.
10 |
11 |
--------------------------------------------------------------------------------
/doc/gettingstartedfulloffline.md:
--------------------------------------------------------------------------------
1 | Getting started with full offline editing
2 | =========================================
3 |
4 | Full offline editing involves setting up your application to survive a browser restart while the mobile device is offline. This short document outlines the various pieces you need to help ensure your web application will work successfully in a full offline environment.
5 |
6 | While this document focuses on editing, some of the patterns recommended here also apply to handling of map tiles while offline.
7 |
8 | **Workflows**
9 |
10 | Here are the top-level application workflows you'll encounter in offline apps:
11 |
12 | - Online + feature layer not extended for offline use = edits always sync with feature service.
13 | - Online + feature layer extended = edits always immediately sync with feature service. Edits pass-thru completely.
14 | - Offline + feature layer extended = edits stored in database and the dataStore is updated by default each time there is a new edit registered.
15 | - Returning online with pending edits + feature layer extended = edits are synced with feature service from local database.
16 | - Returning online with pending edits + feature layer not extended = no edits will be synced.
17 | - Always offline + feature layer extended = you can retrieve the edits programmatically and transfer them to a thumbdrive or equivalent to sync them manually.
18 |
19 | **Overview of the Pieces**
20 |
21 | Restarting a web app offline involves a number of critical pieces that have to be in place. The vast majority of web apps are not designed to survive an offline restart so you have to take extra steps to insure the app reinitializes just like it would if it was online.
22 |
23 | 1. When working with offline apps, you take full responsbility for having a thorough understanding of your application's initialization life cycle. The order in which the various HTML, CSS, .js libraries and image files are parsed by the browser is very important. As you'll find out, if there are any inter-dependencies between libraries, then an offline restart will expose them.
24 | 2. Offline apps will require an Application Cache or Service Workers to pull down all HTML, CSS, .js files and images that an app uses while it is online.
25 | 3. Offline apps require a way to determine if there is an internet connection or not.
26 | 4. Not all JavaScript code will work after an offline restart, such as the Editor Widget. It's safe to assume that the vast majority of JavaScript code ever written was written for fully-online usage and you'll need to take extra care with application initialization.
27 | 5. You'll need to make some decisions on how to manage certain aspects of the feature layer while it is fully offline. OfflineEditAdvanced has a dataStore which you can manually access if needed.
28 |
29 | **Application Life-cycle** Study the full offline samples in this repo carefully. In most cases, they are slightly overengineered. However, they are built that way for good reasons. The order in which things intializes is critical. In many cases don't be surprised if you'll need to force initialization sequences in your code to be sequential. Asynchronous loading of JavaScript libraries typically only works for full offline if you want to wait until all libraries have finished loading.
30 |
31 | **Application Cache.** You will have to set up an application cache file. This cache is also sometimes called Cache Manifest, AppCache and Manifest. The application cache mehanism is broadly supported across [browser vendors](http://caniuse.com/#search=application). It instructs the browser to store any HTML, CSS, .js or image that is required for fully reconstituting the web page while offline. It can be a pain to set these up, it requires a lot of trail and error, but once they are set up they function fairly well.
32 |
33 | Examples of application caches can be found in this repositories `/samples` directory, along with a grunt-based application cache helper tool.
34 |
35 | You may notice warnings that Application Cache has gone away, for example [here on MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache) but the warnings are [greatly exaggerated](http://www.andygup.net/application-cache-is-not-gone-oh-my-or-is-it/).
36 |
37 | **Offline detection for browsers** You need a mechanism for checking if the browser is online or offline. If the browser is offline you can set the `OfflineEditAdvanced` library to offline mode using `OfflineEditAdvanced.goOffline()` and then all edits will be saved to the database. When you want to return online, you can use `OfflineEditAdvanced.goOnline(callback)` and the library will push any pending edits to the Feature Service, and it will also simply pass-thru any and not store anything as long as the library remains in online mode.
38 |
39 | * **[Offline.js](http://caniuse.com/#search=application)** is one library for helping detect if a browser is offline or not. It does have its flaws, for example we've noticed that Chrome on Windows laptops can fail to quickly detect when the browser has gone offline. Detecting when a browser's state shifts from online to offline and back again is tricky business. It's much easier with native SDKs or with plugins for PhoneGap/Cordova.
40 |
41 | * **Simple HTTP request** Another fairly straightforward pattern is to simply try an HTTP request and check if it fails. This isn't completely bulletproof, but it works across all modern browsers. Here's one example:
42 |
43 | ```javascript
44 |
45 | function validateOnline(callback) {
46 | var req = new XMLHttpRequest();
47 | req.open("GET", "http://mywebsite.com/blue-pin.png?" +
48 | (Math.floor(Math.random() * 1000000000)), true);
49 | req.onload = function() {
50 | if( req.status === 200 && req.responseText !== "") {
51 | req = null;
52 | callback(true);
53 | }
54 | else {
55 | console.log("validateOnline failed");
56 | req = null;
57 | callback(false);
58 | }
59 | };
60 | req.onerror = function(e) {
61 | console.log("validateOnline failed: " + e);
62 | callback(false);
63 | };
64 | req.timeout = 10000; //milliseconds
65 | req.send(null);
66 | }
67 |
68 | ```
69 |
70 | **Editing Widgets** The ArcGIS API for JavaScript v3.x Editor Widget does not work in full offline mode for ADDS, UPDATES or DELETES because it doesn't store changes directly in the feature layer.
71 |
72 | You'll need to build your own custom functionality for now. There is an effort underway to create a [light-weight editing template](https://github.com/Esri/offline-editor-js/issues/434) but that is a work in progress and the sample has been temporarily moved to this [gist](https://gist.github.com/andygup/1e768216177dd8a77a73).
73 |
74 | The [appcache-features.html](https://github.com/Esri/offline-editor-js/blob/master/samples/appcache-features.html) sample shows a custom modal widget for doing only UPDATE's on existing data.
75 |
76 | **About the dataStore** The dataStore is a database mechanism for storing feature collections and any other information or objects needed to rebuild an application when it starts up while offline.
77 |
78 | You can either let the library automatically handle the dataStore (default) or you can manually manage it yourself if there's additional items you need to store and maintain between offline browser resarts. In default mode, the library automatically updates the dataStore every time you make an edit. It's sole purpose is to ensure the library has an accurate snapshot of feature layer and its features so that they can be reconstituted correctly.
79 |
80 | More information on how the use the dataStore can be found [here](https://github.com/Esri/offline-editor-js/blob/master/doc/howtouseofmadvancedlibrary.md).
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/doc/howtousetpklibrary.md:
--------------------------------------------------------------------------------
1 | How to use the TPKLayer library
2 | ===============================
3 |
4 | ## `TPKLayer` Library
5 |
6 | The `TPKLayer` Library allows you to display at TPK file as a map.
7 |
8 | **Step 1** Include the `offline-tpk-min.js` library in your app.
9 |
10 | ```js
11 | require([
12 | "esri/map",
13 | "..dist/offline-tpk-min.js"],
14 | function(Map)
15 | {
16 | ...
17 | });
18 | ```
19 |
20 | **Step 2** Unzip the TPK file. This creates an array of Entry objects. Depending on your operating system you may have to rename the TPK file to .zip so that it becomes a recognized MIME type for the html input element.
21 |
22 | ```js
23 |
24 | O.esri.zip.createReader(new O.esri.zip.BlobReader(blob), function (zipReader) {
25 | zipReader.getEntries(function (entries) {
26 | initMap(entries);
27 | zipReader.close(function(evt){
28 | console.log("Done reading zip file.")
29 | })
30 | }, function (err) {
31 | alert("There was a problem reading the file!: " + err);
32 | })
33 | })
34 |
35 |
36 | ```
37 | **Step 3** Create a new instance of TPKLayer and pass the array of Entry objects from the zipReader into the `extend()` method's constructor. Then add the layer to the map. As soon as this code executes the layer will start parsing the TPK file.
38 |
39 |
40 | ```js
41 |
42 | tpkLayer = new O.esri.TPK.TPKLayer();
43 |
44 | //Listen for progress events to provide UX feedback
45 | tpkLayer.on("progress", function (evt) {
46 | evt == "start" ? loading.style.visibility = "visible" : loading.style.visibility = "hidden";
47 | })
48 |
49 | tpkLayer.extend(entries);
50 |
51 | map = new Map("map");
52 | map.addLayer(tpkLayer);
53 |
54 | ```
55 |
56 |
57 |
58 | **Listen for errors**
59 |
60 | It is a best practice to listen for the following events and handle them appropriately in the user interface.
61 |
62 | ```js
63 |
64 | tpkLayer.on("validationEvent", function(evt){
65 | //evt.msg is the string message
66 | //evt.err is the error
67 | if(evt.msg == tpkLayer.NO_SUPPORT_ERROR){
68 | //Let the user know the library isn't supported.
69 | }
70 | })
71 |
72 | tpkLayer.on("databaseErrorEvent", function(evt){
73 | //evt.msg is the string message
74 | //evt.err is the error
75 | if(evt.msg == tpkLayer.DB_INIT_ERROR){
76 | //Let the user know there was a db problem.
77 | }
78 | })
79 |
80 | ```
81 |
82 |
83 | **To clear the database**
84 |
85 | When you need to delete all tiles from the existing data use the following pattern.
86 |
87 | ```js
88 |
89 | tpkLayer.store.deleteAll(function(success,error){
90 | if(success){
91 | //do something
92 | }
93 | else{
94 | //let user know something went wrong
95 | }
96 | })
97 |
98 | ```
99 |
100 | **Can I use the TPKLayer with a tiled basemap?**
101 |
102 | Yes for ArcGIS API for JavaScript v3.8+ and ONLY if the TPKs Levels of Detail (LODs) match the tiled map services LODs exactly.
103 |
104 | The basemap (base tiled layer) defines the LODs that the map can display. Any other operational tiled layers on the map will not display if they don’t match the basemap’s LODs. Esri.Map doesn’t union LODs of all tiled layers on the map.
105 |
106 | You can also use the `TPKLayer.loadFromURL()` method to add tiled map service tiles directly to the database. In order to get the tile information, use this method with `OfflineTilesBasic.saveToFile()` and `OfflineTilesAdvanced.saveToFile()`. That will create a CSV file that contains all the tiles within the extent that you define. The tiles-indexed-db.html sample demonstrates this pattern. Each tile within the CSV is defined by a URL as a String, and the tile image as a base64 String:
107 |
108 | ```js
109 |
110 | var tile = {
111 | url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/16/24710/32091",
112 | img: "data:image/png;base64,iVBORw0KGgoAAA...pQAAAABJRU5ErkJggg=="
113 | };
114 |
115 | ```
116 |
117 | See the [TPKLayer API doc](tpklayer.md) for more info.
118 |
119 | For more information on creating TPKs go [here](http://resources.arcgis.com/en/help/main/10.1/index.html#//006600000457000000).
120 |
121 | **Can I use the TPKLayer with `OfflineEditAdvanced`?**
122 |
123 | Yes, you can use the TPKLayer library alongside the `OfflineEditAdvanced` library. Spatial references must be exactly the same for both the TPK and the feature service.
124 |
125 | **Additional Considerations**
126 |
127 | There are a few things to keep in mind when working with TPK files and JavaScript.
128 |
129 | The following three properties will affect the size of the TPK file. Minimizing all of these will help with application performance. Zoom as close into your area of interest as possible.
130 |
131 | * Number of layers
132 | * Size of the extent
133 | * Minimum and maximum zoom level
134 |
135 | It's a general recommended to keep the size of the local database below 75MBs, with a maximum of 100MBs for best performance. Allowing the database to grow to large can result in browser crashes and slow app performance.
136 |
137 | The library helps where it can by providing 2.7x compression of the tile imagery and about 50% compression of the tile URLs.
138 |
139 | The amount of memory allowed to the browser is dependant on many variables including the available device memory, other applications already running and the number of open browser tabs.
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/doc/migratefromv1tov2.md:
--------------------------------------------------------------------------------
1 | # Migrating from v1 to v2
2 |
3 | This doc is to provide pointers for migrating from offline-editor-js v1 to v2. Migration should be fairly straightforward as you are simply going to be changing library names and method namespaces. Check the CHANGELOG doc for specifics as well as any deprecations.
4 |
5 |
6 | ## Importing the libraries
7 |
8 | In your main html application you can use generic script injection to import the offline-editor-js libraries into your project. Don't create any aliases for the offline-editor-js libraries within the function statement and add them to the end of the module array, but before domReady. As you can see in the example below, the only alias is for `Map`.
9 |
10 | ```html
11 |
12 |
110 |
111 |
256 |
257 |