diff --git a/.gitmodules b/.gitmodules index 682efeec..ac070090 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,3 @@ -[submodule "vendor/offline"] - path = vendor/offline - url = https://github.com/HubSpot/offline.git -[submodule "vendor/IndexedDBShim"] - path = vendor/IndexedDBShim - url = https://github.com/axemclion/IndexedDBShim.git [submodule "vendor/jasmine.async"] path = vendor/jasmine.async url = https://github.com/derickbailey/jasmine.async.git diff --git a/CHANGELOG.md b/CHANGELOG.md index 331da73f..eeb05bb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,40 @@ # offline-editor-js - Changelog +## Version 3.0 - Nov. 23, 2015 + +Has many breaking changes due to new naming conventions. + +This version adds a new, lightweight (14Kb) editing library aimed at intermittent offline-only workflows. And, there was a significant amount of refactoring aimed at fixing and simplifying the library's naming conventions. + +This version implements a consistent naming convention that uses "basic" and "advanced". If `basic` is in the name of the distribution library that means support for intermittent offline-only. `advanced` in the name means support for both intermittent and full offline usage including browser restarts while offline. + +In general, migrating from v2.x to 3.x should be a straightforward exercise in simple refactoring of library names. + +**Enhancements** +* Creates a new `OfflineEditBasic` library. This lightweight (14Kb) library is designed specifically for easy use and intermittent offline-only editing use cases. +* Created `offline-edit-basic` and `offline-edit-advanced` for both `src` and `min` versions. +* Updates documentation, samples and unit tests to reflect the name changes. + +**Refactored** +* `offlineFeaturesManager.js` renamed `OfflineEditAdvanced.js`. No other changes were made to this library. +* `offlineTilesEnabler.js` renamed `OfflineTilesBasic.js`. +* `OfflineTilesEnablerLayer.js` renamed `OfflineTilesAdvanced`. No other changes made. +* `tiles-indexed-db.html` renamed to `simple-tiles.html`. +* All samples have been updated to reflect the new library names. +* All test specs have been updated and refactored to reflect the new library names. + +**Deprecated** +* Deprecated `offline-edit-min.js` and `offline-edit-src.js`. +* In `OfflineEditAdvanced.js` removed deprecated functions `_cleanSuccessfulEditsDatabaseRecords()`, `_internalApplyEdits()`. +* In `editStore.js` removed deprecated function `resetLimitedPhantomGraphicsQueue()`. +* In `editStore.js` removed unused functions `_serialize()`, `_deserialize()`. +* Deleted `/demo/samples` directory. +* Removed Offline.js and IndexedDBShim from sub-module depencies. You'll need to reference these via their respective CDNs for gh-pages URL. + +**Bug Fixes** +* Minor - `OfflineEditAdvanced` no longer throws an error when reinitialized with a featureCollection. + + ## Version 2.16 - Oct. 29, 2015 No breaking changes. Recommended update. diff --git a/Gruntfile.js b/Gruntfile.js index 7456cd5d..c906e075 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -28,8 +28,8 @@ module.exports = function(grunt) { 'Gruntfile.js', 'lib/edit/*.js', 'lib/tiles/base64utils.js', - 'lib/tiles/OfflineTilesEnabler.js', - 'lib/tiles/OfflineTilesEnablerLayer.js', + 'lib/tiles/OfflineTilesBasic.js', + 'lib/tiles/OfflineTilesAdvanced.js', 'lib/tiles/OfflineTilesNS.js', 'lib/tiles/TilesCore.js', 'lib/tiles/TilesStore.js', @@ -49,19 +49,29 @@ module.exports = function(grunt) { '*/\n' }, /* All feature editing capabilities: adds, updates and deletes */ - edit: { + editAdvanced: { src: [ - 'lib/edit/offlineFeaturesManager.js', + 'lib/edit/offlineJSOptions.js', + 'lib/edit/OfflineEditAdvanced.js', 'lib/edit/OfflineEditNS.js', 'lib/edit/editsStore.js', 'lib/edit/attachmentsStore.js' ], - dest: 'dist/offline-edit-src.js' + dest: 'dist/offline-edit-advanced-src.js' + }, + editBasic: { + src: [ + 'lib/edit/offlineJSOptions.js', + 'lib/edit/OfflineEditBasic.js', + 'lib/edit/OfflineEditNS.js', + 'lib/edit/editStorePOLS.js' + ], + dest: 'dist/offline-edit-basic-src.js' }, /* Tiles basic is for use with WebMaps. Cannot be reloaded or restarted while offline */ tilesBasic: { src: [ - 'lib/tiles/offlineTilesEnabler.js', + 'lib/tiles/OfflineTilesBasic.js', 'lib/tiles/OfflineTilesNS.js', 'lib/tiles/base64utils.js', 'lib/tiles/FileSaver.js', @@ -74,7 +84,7 @@ module.exports = function(grunt) { /* Tiles advanced is for use with tiled map services. Works with reload or restart while offline */ tilesAdvanced: { src: [ - 'lib/tiles/offlineTilesEnablerLayer.js', + 'lib/tiles/OfflineTilesAdvanced.js', 'lib/tiles/OfflineTilesNS.js', 'lib/tiles/base64utils.js', 'lib/tiles/FileSaver.js', @@ -104,6 +114,9 @@ module.exports = function(grunt) { compress: { drop_console: true //remove console.log statements :) }, + beautify: { + semicolons: false //Required: prevents dojo parser errors w/ minified files in this project + }, preserveComments: 'some', wrap: false // mangle: { @@ -112,7 +125,8 @@ module.exports = function(grunt) { }, dist: { files: { - 'dist/offline-edit-min.js': ['dist/offline-edit-src.js'], + 'dist/offline-edit-advanced-min.js': ['dist/offline-edit-advanced-src.js'], + 'dist/offline-edit-basic-min.js': ['dist/offline-edit-basic-src.js'], 'dist/offline-tiles-basic-min.js': ['dist/offline-tiles-basic-src.js'], 'dist/offline-tiles-advanced-min.js': ['dist/offline-tiles-advanced-src.js'], 'dist/offline-tpk-min.js': ['dist/offline-tpk-src.js'] diff --git a/README.md b/README.md index 3ef71d27..38b64183 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,28 @@ offline-editor-js ================= -Offline-editor-js is a family of libraries for building offline capabilities into web mapping applications. It's specifically designed to work with the ArcGIS API for JavaScript and ArcGIS Online. It enables you to store feature edits, attachments, map tiles and TPKs (Tile Packages). +Offline-editor-js is a family of libraries for building offline capabilities into web mapping applications. It's specifically designed to work with the ArcGIS API for JavaScript and ArcGIS Online. With these libraries you can store feature edits, attachments, map tiles and TPKs (Tile Packages). + +***IMPORTANT:*** If you need a fully integrated, robust offline solution then you should be using our native ArcGIS Runtime SDKs for .NET, WPF, Java, iOS, Android and Qt. + +# Getting Started Online samples and getting started tutorials are available here: **[http://esri.github.io/offline-editor-js/demo/](http://esri.github.io/offline-editor-js/demo/)** -*IMPORTANT:* If you need a fully integrated, robust offline solution then you should be using our native ArcGIS Runtime SDKs for .NET, WPF, Java, iOS, Android and Qt. -This repo contains the following libraries: +# Libraries + +This repo contains the following libraries in the `/dist` directory. The use of `basic` in the name indicates intermittent offline-only, and `advanced` indicates the library can be used for both intermittent and full offline. + +Use_Case | Name, Description and gh-pages URL +--- | --- +Basic editing | **`offline-edit-basic-min.js`** Simple, lightweight *(14k minimized)* offline editing library that automatically caches adds, updates and deletes when the internet is temporarily interrupted.

[`http://esri.github.io/offline-editor-js/dist/offline-edit-basic-min.js`](http://esri.github.io/offline-editor-js/dist/offline-edit-basic-min.js) +Advanced editing | **`offline-edit-advanced-min.js`** Used for intermittent and full offline editing workflows. Also includes limited support for attachments.

[`http://esri.github.io/offline-editor-js/dist/offline-edit-advanced-min.js`](http://esri.github.io/offline-editor-js/dist/offline-edit-advanced-min.js) +Basic map tiles | **`offline-tiles-basic-min.js`** Caches map tiles for simple, intermittent-only offline workflows. Use this library with ArcGIS Online Web maps as well as with tiled map services.

[`http://esri.github.io/offline-editor-js/dist/offline-tiles-basic-min.js`](http://esri.github.io/offline-editor-js/dist/offline-tiles-basic-min.js) +Advanced map tiles | **`offline-tiles-advanced-min.js`** Used for intermittent and full offline tile caching. Extends any ArcGIS Tiled Map Service. This library should be used in conjunction with an HTML5 Application Cache Manifest coding pattern.

[`http://esri.github.io/offline-editor-js/dist/offline-tiles-advanced-min.js`](http://esri.github.io/offline-editor-js/dist/offline-tiles-advanced-min.js) +TPK files | **`offline-tpk-min.js`** Reads TPK files and displays and caches them as a tiled map layer.

[`http://esri.github.io/offline-editor-js/dist/offline-tpk-min.js`](http://esri.github.io/offline-editor-js/dist/offline-tpk-min.js) -- `/dist` - contains src and min versions of each library: - * `offline-edit-min.js` - stores adds, updates and deletes of features as well as limited attachment support while offline. Resync's edits with server once connection is reestablished. - * `offline-tiles-basic-min.js` - caches map tiles for partial offline use cases. Use this library with ArcGIS Online Web maps as well as with tiled map services. This repo will not work with browser restarts or reloads while offline. - * `offline-tiles-advanced-min.js` - Extends any ArcGIS Tiled Map Service that has a requirement for offline browser reload and/or restart. This library should be used in conjunction with an HTML5 application cache coding pattern. - * `offline-tpk-min.js` - parses a TPK file and displays it as a tiled map layer. -- `/utils`: contains various helper library modules. These modules are all AMD compliant. -- `/samples`: samples that show how to use the different offline libraries capabilities. +`src` files are for software development-only. The`min` versions are minified and should be used in production. #Workflows Supported The following workflow is currently supported for both both features and tiles: @@ -63,6 +70,7 @@ Go __[here](https://github.com/Esri/offline-editor-js/wiki/FAQ)__ for answers to ##Limitations * Currently does not support related tables, domains or subtypes. The ArcGIS Runtime SDKs fully support these and more. +* There are browser limitations and technical dependencies. The offline capabilities in this toolkit depend on certain JavaScript capabilities being present in the browser. Go [here](doc/dependencies.md) for a detailed breakdown. * Attachments are supported with some limitations listed [here](./doc/attachments.md). * Browser storage space on mobile devices is a known limitation. This applies to stand-alone web applications and hybrid applications. @@ -72,17 +80,15 @@ Go __[here](https://github.com/Esri/offline-editor-js/wiki/FAQ)__ for answers to ##Dependencies -* ArcGIS API for JavaScript (v3.12+) +* [ArcGIS API for JavaScript (v3.12+)](https://developers.arcgis.com/javascript/) +* [Offline.js](http://github.hubspot.com/offline/docs/welcome/) - it allows detection of the online/offline condition and provides events to hook callbacks on when this condition changes * Node.js required for building the source -* NOTE: browser limitations and technical dependencies. The offline capabilities in this toolkit depend on certain HTML5 capabilities being present in the browser. Go [here](doc/dependencies.md) for a detailed breakdown of the information. +* [IndexedDBShim](https://github.com/axemclion/IndexedDBShim) - polyfill to simulate indexedDB functionality in browsers/platforms where it is not supported notably older versions desktop Safari and iOS Safari. * Sub-modules (see `/vendor` directory) - * [offline.js](https://github.com/hubspot/offline) - it allows detection of the online/offline condition and provides events to hook callbacks on when this condition changes - * [IndexedDBShim](https://github.com/axemclion/IndexedDBShim) - polyfill to simulate indexedDB functionality in browsers/platforms where it is not supported (notably desktop Safari and iOS Safari) - - IMPORTANT: There are known [issues](https://github.com/axemclion/IndexedDBShim/issues/115) with IndexedDBShim on Safari. For Safari, the storage error workaround is to switch from using /dist/IndexedDBShim.min.js to just using IndexedDBShim.js and then search for and modify the line that defines the value for `DEFAULT_DB_SIZE`. Set this to more appropriate size that will meet all your storage needs, for example: ```var DEFAULT_DB_SIZE = 24 * 1024 * 1024``` - * [jasmine.async](https://github.com/derickbailey/jasmine.async.git) - library to help implementing tests of async functionality (used in tests) + * [jasmine.async](https://github.com/derickbailey/jasmine.async.git) - Used specifically for unit testing. -* Non sub-module based libraries +* Non sub-module based libraries that are used internally by this project * [FileSaver.js](https://github.com/Esri/offline-editor-js/blob/master/lib/tiles/README.md) - library to assist with uploading and downloading of files containing tile information. * [grunt-manifest](https://github.com/gunta/grunt-manifest) node.js library to assist with the creation of manifest files. * [zip](http://gildas-lormeau.github.io/zip.js/) A library for zipping and unzipping files. diff --git a/demo/api-doc.html b/demo/api-doc.html index 5e2b57e6..a75b5169 100644 --- a/demo/api-doc.html +++ b/demo/api-doc.html @@ -71,18 +71,17 @@

API Docs

-

Offline Tiles - Basic

-

The offline-tiles-basic-min.js library is for use with ArcGIS.com web maps and partial/intermittently offline use cases. - You won't be able to restart or reload your app when using this library offline. +

Offline Editing - Basic

+

The offline-edit-basic-min.js library is for working with ArcGIS JS API points, lines and polygons in intermittent offline use cases, only.

@@ -90,15 +89,33 @@

Offline Tiles - Basic

-

Offline Tiles - Advanced

-

The offline-tiles-advanced-min.js library is for use with tiled map services in partial or fully offline use cases. - If you have a requirement to reload or restart your app while offline you should use this library. +

Offline Editing - Advanced

+

The offline-edit-advanced-min.js library is for working with ArcGIS JS API points, lines and polygons in intermittent and full offline use cases. +

+
+ +
+ +
+
+

Offline Tiles - Basic

+

The offline-tiles-basic-min.js library is for use with ArcGIS.com web maps and partial/intermittently offline use cases. + You won't be able to restart or reload your app when using this library offline.

  • - O.esri.Tiles.OfflineTilesEnablerLayer + O.esri.Tiles.OfflineTilesBasic
  • How to use. @@ -109,17 +126,18 @@

    Offline Tiles - Advanced

    -

    Offline Features

    -

    The offline-edit-min.js library is for working with ArcGIS JS API points, lines and polygons in partial or fully offline use cases. +

    Offline Tiles - Advanced

    +

    The offline-tiles-advanced-min.js library is for use with tiled map services in partial or fully offline use cases. + If you have a requirement to reload or restart your app while offline you should use this library.

    @@ -128,13 +146,13 @@

    Offline Features

    Offline Attachments

    -

    The offline-edit-min.js library provides limited supported for attachments. +

    The offline-edit-advanced-mins.js library has limited attachment support. The offline-edit-basic-min.js library pffers no support for attachments.

    • - O.esri.Edit.OfflineFeaturesManager + O.esri.Edit.OfflineEditAdvanced
    • How to use. diff --git a/demo/css/style.css b/demo/css/style.css index 211fc10c..91619905 100644 --- a/demo/css/style.css +++ b/demo/css/style.css @@ -11,8 +11,16 @@ body { height: 50px; line-height: 20px; font-size: large; - color: #ffffff; + color: #000000; } +.navbar { + background-color: #6699cc !important; +} + +.navbar-nav:hover { + color: black; +} + .navbar-brand-title:hover { color: lightgray; text-decoration: none; diff --git a/demo/getstarted-agol.html b/demo/getstarted-agol.html deleted file mode 100644 index 5d802cf2..00000000 --- a/demo/getstarted-agol.html +++ /dev/null @@ -1,862 +0,0 @@ - - - - - - - - - Offline-editor-js - - - - - - - - - - - - - - - - - - - - - - - -
      -
      -

      Getting Started with ArcGIS.com

      -

      Basic steps for working with ArcGIS.com base maps for offline.

      - -
      -
      - -
      - -
      -
      - - - -
      -
      -

      Step 1: Fill in the basics

      -

      Add the basic library references. Then test to make sure map loads.

      -
      -
      -                        
      -<!DOCTYPE html>
      -<html>
      -<head>
      -    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      -    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
      -    <title>Offline ArcGIS.com</title>
      -
      -    <!-- Bootstrap core CSS -->
      -    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
      -
      -    <link rel="stylesheet" href="http://js.arcgis.com/3.11/esri/css/esri.css"">
      -    <link rel="stylesheet" type="text/css" href="http://esri.github.io/bootstrap-map-js/src/css/bootstrapmap.css">
      -    <style>
      -        #mapDiv {
      -            min-height: 500px;
      -            max-height: 1000px;
      -        }
      -        body {
      -            background-color: #ffffff;
      -            overflow: hidden;
      -            font-family: "Trebuchet MS";
      -        }
      -        .floatRight {float: right;}
      -        .container { padding: 20px;}
      -    </style>
      -
      -    <!-- Include a reference to offline.js which detects online/offline conditions -->
      -    <script src="../vendor/offline/offline.min.js"></script>
      -    <script>
      -        // Set the online/offline detection options.
      -        // More info at: http://github.hubspot.com/offline/docs/welcome/
      -        Offline.options = {
      -            checks: {
      -                image: {
      -                    url: function() {
      -                        return 'http://esri.github.io/offline-editor-js/tiny-image.png?_=' +
      -                                (Math.floor(Math.random() * 1000000000));
      -                    }
      -                },
      -                active: 'image'
      -            }
      -        }
      -    </script>
      -
      -    <!-- Include a reference to IndexedDBShim for library to work on Safari 7.x -->
      -    <script src="../vendor/IndexedDBShim/dist/IndexedDBShim.js"></script>
      -
      -    <script src="http://js.arcgis.com/3.11/"></script>
      -</head>
      -
      -<body>
      -
      -<div class="container">
      -    <div class="row">
      -        <div class="col-xs-12">
      -            <div id="mapDiv"></div>
      -        </div>
      -    </div>
      -</div>
      -
      -<script>
      -
      -    // Make sure to reference the tiles library within the require statement!
      -    require([
      -        "esri/map",
      -        "dojo/on",
      -        "esri/arcgis/utils",
      -        "//esri.github.com/bootstrap-map-js/src/js/bootstrapmap.js",
      -        "../dist/offline-tiles-basic-src.js",
      -        "dojo/domReady!"],
      -        function(Map,on,arcgisUtils,BootstrapMap) {
      -
      -            var map;
      -
      -            // Load the map
      -            arcgisUtils.createMap("bbc1a04a3eca4430be144d7a08b43a17","mapDiv").then(function(response){
      -                var map = response.map;
      -
      -                map = response.map;
      -
      -                // Initialize BootstrapMap to make the map responsive
      -                BootstrapMap.create(map);
      -
      -            });
      -        });
      -</script>
      -
      -
      -<!-- Bootstrap core JavaScript
      -================================================== -->
      -<!-- Placed at the end of the document so the pages load faster -->
      -<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      -<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
      -
      -</body>
      -</html>
      -
      -                        
      -                    
      -
      NOTE: Replace paths with your references. Or build your app in the /demo directory
      -
      -
      -

      Step 2: Extend basemap using the offline library

      -

      This initializes the OfflineTilesEnabler library and tells it which tiled map service layer to use for offline. Test to make sure map loads.

      -
      - -
      -                        
      -<!DOCTYPE html>
      -<html>
      -<head>
      -    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      -    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
      -    <title>Offline ArcGIS.com</title>
      -
      -    <!-- Bootstrap core CSS -->
      -    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
      -
      -    <link rel="stylesheet" href="http://js.arcgis.com/3.11/esri/css/esri.css">
      -    <link rel="stylesheet" type="text/css" href="http://esri.github.io/bootstrap-map-js/src/css/bootstrapmap.css">
      -    <style>
      -        html, body, #map {
      -            height: 100%;
      -            width: 100%;
      -            margin: 0;
      -            padding: 0;
      -        }
      -        body {
      -            background-color: #000000;
      -            overflow: hidden;
      -            font-family: "Trebuchet MS";
      -        }
      -        .floatRight {float: right;}
      -        .container { padding: 20px;}
      -    </style>
      -
      -    <!-- Include a reference to offline.js which detects online/offline conditions -->
      -    <script src="../vendor/offline/offline.min.js"></script>
      -    <script>
      -        // Set the online/offline detection options.
      -        // More info at: http://github.hubspot.com/offline/docs/welcome/
      -        Offline.options = {
      -            checks: {
      -                image: {
      -                    url: function() {
      -                        return 'http://esri.github.io/offline-editor-js/tiny-image.png?_=' +
      -                                (Math.floor(Math.random() * 1000000000));
      -                    }
      -                },
      -                active: 'image'
      -            }
      -        }
      -    </script>
      -
      -    <!-- Include a reference to IndexedDBShim for library to work on Safari 7.x -->
      -    <script src="../vendor/IndexedDBShim/dist/IndexedDBShim.js"></script>
      -
      -    <script src="http://js.arcgis.com/3.11/"></script>
      -</head>
      -
      -<body>
      -
      -<div class="row">
      -    <div class="col-xs-12">
      -        <div id="mapDiv"></div>
      -    </div>
      -</div>
      -
      -<script>
      -
      -    // Make sure to reference the tiles library within the require statement!
      -    require([
      -        "esri/map",
      -        "dojo/on",
      -        "esri/arcgis/utils",
      -        "//esri.github.com/bootstrap-map-js/src/js/bootstrapmap.js",
      -        "../dist/offline-tiles-basic-src.js",
      -        "dojo/domReady!"],
      -        function(Map,on,arcgisUtils,BootstrapMap) {
      -
      -            var map, basemapLayer;
      -            var offlineTilesEnabler = new O.esri.Tiles.OfflineTilesEnabler();
      -
      -            showMap();
      -
      -
      -            function showMap(){
      -                // Load the map
      -                arcgisUtils.createMap("bbc1a04a3eca4430be144d7a08b43a17","mapDiv").then(function(response){
      -                    map = response.map;
      -
      -                    // Initialize BootstrapMap to make the map responsive
      -                    BootstrapMap.create(map);
      -
      -                    // Get the ArcGIS.com basemap that we want to use offline.
      -                    // And then extend it for offline use.
      -                    if(map.loaded)
      -                    {
      -                        basemapLayer = map.getLayer( map.layerIds[0] );
      -                        initializeOfflineTiles();
      -
      -                    }
      -                    else
      -                    {
      -                        map.on("load",function()
      -                        {
      -                            basemapLayer = map.getLayer( map.layerIds[0] );
      -                            initializeOfflineTiles();
      -                        });
      -                    }
      -
      -                });
      -            }
      -
      -            function initializeOfflineTiles(){
      -                offlineTilesEnabler.extend(basemapLayer,function(success) {
      -                    if (success) {
      -                        console.log("ArcGIS.com map extended for offline!")
      -                    }
      -                })
      -            }
      -        });
      -</script>
      -
      -
      -<!-- Bootstrap core JavaScript
      -================================================== -->
      -<!-- Placed at the end of the document so the pages load faster -->
      -<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      -<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
      -
      -</body>
      -</html>
      -
      -                        
      -                    
      -
      NOTE: Replace paths with your references. Or build your app in the /demo directory
      - -
      - -
      -

      Step 3: Configure tiles download.

      -

      Enable the ability to download tiles as well the ability to toggle online and offline.

      -
      - - - -
      - - -
      -
      -
      -                            
      -
      -<!DOCTYPE html>
      -<html>
      -<head>
      -    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      -    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
      -    <title>Offline ArcGIS.com</title>
      -
      -    <!-- Bootstrap core CSS -->
      -    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
      -
      -    <link rel="stylesheet" href="http://js.arcgis.com/3.11/esri/css/esri.css">
      -    <link rel="stylesheet" type="text/css" href="http://esri.github.io/bootstrap-map-js/src/css/bootstrapmap.css">
      -    <style>
      -        #mapDiv {
      -            min-height: 500px;
      -            max-height: 1000px;
      -        }
      -        body {
      -            background-color: #ffffff;
      -            overflow: hidden;
      -            font-family: "Trebuchet MS";
      -        }
      -
      -        .floatRight {float: right;}
      -        .container { padding: 20px;}
      -    </style>
      -
      -    <!-- Include a reference to offline.js which detects online/offline conditions -->
      -    <script src="../vendor/offline/offline.min.js"></script>
      -    <script>
      -        // Set the online/offline detection options.
      -        // More info at: http://github.hubspot.com/offline/docs/welcome/
      -        Offline.options = {
      -            checks: {
      -                image: {
      -                    url: function() {
      -                        return 'http://esri.github.io/offline-editor-js/tiny-image.png?_=' +
      -                                (Math.floor(Math.random() * 1000000000));
      -                    }
      -                },
      -                active: 'image'
      -            }
      -        }
      -    </script>
      -
      -    <!-- Include a reference to IndexedDBShim for library to work on Safari 7.x -->
      -    <script src="../vendor/IndexedDBShim/dist/IndexedDBShim.js"></script>
      -
      -    <script src="http://js.arcgis.com/3.11/"></script>
      -</head>
      -
      -<body>
      -
      -<div class="container">
      -    <div class="row">
      -        <div class="col-xs-10">
      -            <div class="form form-group btn-group" data-toggle="buttons">
      -                <button class="btn btn-success" id="btn-get-tiles">1. Download Tiles</button>
      -                <button class="btn btn-success" disabled id="btn-online-offline">2. Go Offline</button>
      -                <button class="btn btn-success" disabled id="btn-pan-left">3. Pan left</button>
      -            </div>
      -        </div>
      -        <div class="col-xs-2">
      -            <!-- this indicates whether app is offline (down) or online (up) -->
      -            <button id="btn-state" class="btn btn-success btn-large floatRight">
      -                <span id="state-span" class="glyphicon glyphicon-link"> Up</span>
      -            </button>
      -        </div>
      -    </div>
      -    <div class="row">
      -        <div class="col-xs-12">
      -            <div id="mapDiv"></div>
      -        </div>
      -    </div>
      -</div>
      -
      -<script>
      -
      -    // Make sure to reference the tiles library within the require statement!
      -    require([
      -        "esri/map",
      -        "dojo/on",
      -        "esri/arcgis/utils",
      -        "//esri.github.com/bootstrap-map-js/src/js/bootstrapmap.js",
      -        "../dist/offline-tiles-basic-src.js",
      -        "dojo/domReady!"],
      -        function(Map,on,arcgisUtils,BootstrapMap) {
      -
      -            var map, basemapLayer;
      -            var offlineTilesEnabler = new O.esri.Tiles.OfflineTilesEnabler();
      -
      -            // Check if browser state is online or offline
      -            Offline.check();
      -            Offline.on('up down', updateState );
      -
      -            // For cancelling the download of tiles
      -            var _wantToCancel;
      -            var _downloadState = "downloaded";
      -
      -            // Set up min and max boundaries for retrieving tiles
      -            var minZoomAdjust = -1, maxZoomAdjust = 1, mMinZoom, mMaxZoom;
      -
      -            // Set up button click listeners.
      -            var btnGetTiles = document.getElementById("btn-get-tiles");
      -            var btnOnlineOffline = document.getElementById("btn-online-offline");
      -            var btnPanLeft = document.getElementById("btn-pan-left");
      -
      -            var imgOfflineIndicator = document.getElementById("state-span");
      -            var btnState = document.getElementById("btn-state");
      -
      -            on(btnGetTiles,"click",downloadTiles);
      -            on(btnOnlineOffline,"click",goOnlineOffline);
      -            on(btnPanLeft,"click",panLeft);
      -
      -            showMap();
      -
      -
      -            function showMap(){
      -                // Load the map
      -                arcgisUtils.createMap("bbc1a04a3eca4430be144d7a08b43a17","mapDiv").then(function(response){
      -                    map = response.map;
      -
      -                    // Initialize BootstrapMap to make the map responsive
      -                    BootstrapMap.create(map);
      -
      -                    // Get the ArcGIS.com basemap that we want to use offline.
      -                    // And then extend it for offline use.
      -                    if(map.loaded)
      -                    {
      -                        basemapLayer = map.getLayer( map.layerIds[0] );
      -                        initializeOfflineTiles();
      -
      -                    }
      -                    else
      -                    {
      -                        map.on("load",function()
      -                        {
      -                            basemapLayer = map.getLayer( map.layerIds[0] );
      -                            initializeOfflineTiles();
      -                        });
      -                    }
      -
      -                });
      -            }
      -
      -            function initializeOfflineTiles(){
      -                offlineTilesEnabler.extend(basemapLayer,function(success) {
      -                    if (success) {
      -                        console.log("ArcGIS.com map extended for offline!")
      -                    }
      -                })
      -            }
      -
      -            function downloadTiles(){
      -
      -                if(_downloadState == "downloading"){
      -                    _wantToCancel = true;
      -                }
      -                else{
      -                    _wantToCancel = false;
      -
      -                    // First delete any existing tiles from database
      -                    basemapLayer.deleteAllTiles(function(success,err){
      -                        var zoom = basemapLayer.getMinMaxLOD(minZoomAdjust,maxZoomAdjust);
      -
      -                        // Now download tiles
      -                        basemapLayer.prepareForOffline(zoom.min, zoom.max, map.extent, function(progress){
      -                            console.log("downloading tiles...");
      -
      -                            if(progress.hasOwnProperty("countNow")){
      -                                var percent = Math.floor(progress.countNow / progress.countMax * 100);
      -                                btnGetTiles.innerHTML = 'Saving to phone ' + percent + "% - Tap to Cancel";
      -                            }
      -
      -                            if( progress.finishedDownloading )
      -                            {
      -                                btnGetTiles.innerHTML = "Saving to phone 100% - Tap to Cancel";
      -
      -                                if( progress.cancelRequested )
      -                                {
      -                                    alert("Tile download was cancelled");
      -                                    _downloadState = "cancelled";
      -                                }
      -                                else
      -                                {
      -                                    alert("Tile download complete");
      -                                    _downloadState = "downloaded";
      -                                    btnOnlineOffline.disabled = false;
      -                                }
      -
      -                                btnGetTiles.innerHTML = '1. Download Tiles';
      -                            }
      -                            return _wantToCancel; //determines if a cancel request has been issued
      -                        });
      -
      -                        _downloadState = "downloading";
      -
      -                    });
      -                }
      -            }
      -
      -            // Force the tileLayer between online and offline
      -            function goOnlineOffline(){
      -
      -                btnPanLeft.disabled = false;
      -
      -                if(btnOnlineOffline.innerHTML == "2. Go Offline"){
      -                    toggleStateUp(false);
      -                    console.log("Map is offline");
      -                }
      -                else{
      -                    toggleStateUp(true);
      -                    console.log("Map is online");
      -                }
      -            }
      -
      -            function toggleStateUp(state){
      -                if(state){
      -                    btnOnlineOffline.innerHTML = "2. Go Offline";
      -                    basemapLayer.goOnline();
      -                    imgOfflineIndicator.className = "glyphicon glyphicon-link";
      -                    imgOfflineIndicator.innerHTML = " Up";
      -                    btnState.className = "btn btn-success btn-large floatRight";
      -                }
      -                else{
      -                    btnOnlineOffline.innerHTML = "2. Go Online";
      -                    basemapLayer.goOffline();
      -                    imgOfflineIndicator.className = "glyphicon glyphicon-thumbs-down";
      -                    imgOfflineIndicator.innerHTML = " Down";
      -                    btnState.className = "btn btn-danger btn-large floatRight";
      -                }
      -            }
      -
      -            // Set the ArcGIS.com map online or offline.
      -            // When set offline it will look for tiles in the tiles database
      -            function updateState(){
      -                if(Offline.state === 'up'){
      -                    if(typeof basemapLayer != "undefined") basemapLayer.goOnline();
      -                    toggleStateUp(true);
      -                }
      -                else{
      -                    if(typeof basemapLayer != "undefined") basemapLayer.goOffline();
      -                    toggleStateUp(false);
      -                }
      -            }
      -
      -            // Pan left when "offline" to view only tiles that have been stored locally
      -            function panLeft(){
      -                map.panLeft();
      -            }
      -        });
      -</script>
      -
      -
      -<!-- Bootstrap core JavaScript
      -================================================== -->
      -<!-- Placed at the end of the document so the pages load faster -->
      -<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      -<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
      -
      -</body>
      -</html>
      -
      -                            
      -                        
      -
      NOTE: Replace paths with your references. Or build your app in the /demo directory
      -
      - -
      -
      -
      -
      - - - -
      -
      -
      - - -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - -
      -
      -
      -
      -
      - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/demo/getstarted-editing.html b/demo/getstarted-editing.html deleted file mode 100644 index b7dbd779..00000000 --- a/demo/getstarted-editing.html +++ /dev/null @@ -1,1208 +0,0 @@ - - - - - - - - - Get Started Editing - - - - - - - - - - - - - - - - - - - - - - - -
      -
      -

      Getting Started with Editing

      -

      Basic steps for working with Editing geographic features for offline.

      - -
      -
      - -
      - -
      -
      - - - -
      -
      -

      Step 1: Fill in the basics

      -

      Add library references and build basic layout. Then test to make sure map loads. - A fully working and editable version of this step is included in /demo/samples/editing-step1.html.

      -
      -
      -                        
      -<!DOCTYPE html>
      -<html>
      -<head>
      -    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      -    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
      -    <title>Offline Features</title>
      -    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
      -    <link rel="stylesheet" href="//js.arcgis.com/3.13/esri/css/esri.css">
      -    <link rel="stylesheet" href="../widgets/modal/css/modal-popup.css">
      -    <link rel="stylesheet" type="text/css" href="http://esri.github.io/bootstrap-map-js/src/css/bootstrapmap.css">
      -    <style>
      -        #mapDiv {
      -            min-height: 500px;
      -            max-height: 1000px;
      -        }
      -
      -        #img-offline-indicator {
      -            padding: 8px;
      -            position: relative; float: right;
      -        }
      -
      -        /* Override mod-popup default */
      -        .mod-popup-stop-input {color: black;}
      -        .span-pending {color: blue; padding-left: 1em;}
      -        .voffset20px { margin-top: 20px; }
      -        .floatRight { float: right}
      -    </style>
      -
      -    <!-- Include a reference to offline.js which detects online/offline conditions -->
      -    <script src="../../vendor/offline/offline.min.js"></script>
      -    <script>
      -        // Set how we pull in custom AMD modules
      -        var path = location.pathname.replace(/[^\/]+$/, '');
      -        var dojoConfig =
      -        {
      -            debug: true,
      -            packages:[
      -                {
      -                    name: "widgets",
      -                    location: path + "../widgets/modal/"
      -                }]
      -        }
      -
      -        // Set the online/offline detection options.
      -        // More info at: http://github.hubspot.com/offline/docs/welcome/
      -        Offline.options = {
      -            checks: {
      -                image: {
      -                    url: function() {
      -                        return 'http://esri.github.io/offline-editor-js/tiny-image.png?_=' +
      -                                (Math.floor(Math.random() * 1000000000));
      -                    }
      -                },
      -                active: 'image'
      -            }
      -        }
      -    </script>
      -
      -    <script src="//js.arcgis.com/3.13/"></script>
      -</head>
      -
      -<body>
      -
      -<div class="container voffset20px">
      -    <div class="row">
      -        <div class="col-xs-8">
      -            <button class="btn btn-success" id="btn-online-offline">Go Offline</button>
      -            <span class="span-pending">Pending Edits <span id="span-pending-edits" class="badge">0</span></span>
      -        </div>
      -        <div class="col-xs-4">
      -            <button id="btn-state" class="btn btn-success btn-large floatRight">
      -                <span id="state-span" class="glyphicon glyphicon-link"> Up</span>
      -            </button>
      -        </div>
      -    </div>
      -    <div class="row voffset20px">
      -        <div class="col-xs-12">
      -            <div id="mapDiv"></div>
      -        </div>
      -    </div>
      -</div>
      -<!-- Stub for modal popup -->
      -<div id="modal-popup"></div>
      -
      -<script>
      -
      -    require([
      -                "esri/map","esri/tasks/query",
      -                "dojo/on","dojo/parser", "esri/renderers/SimpleRenderer",
      -                "esri/symbols/SimpleMarkerSymbol","esri/Color",
      -                "widgets/popup","esri/layers/FeatureLayer",
      -                "//esri.github.com/bootstrap-map-js/src/js/bootstrapmap.js",
      -                "../../dist/offline-edit-src.js",
      -                "dojo/domReady!"],
      -            function(Map,Query,on,parser,SimpleRenderer,SimpleMarkerSymbol,
      -                     Color,ModalPopup,FeatureLayer,BootstrapMap){
      -
      -                var map, popup, editsStore;
      -                var defaultSymbol;
      -                var offlineFeaturesManager;
      -                var btnOnlineOffline, btnState, pendingEdits;
      -                var imgOfflineIndicator;
      -                var closeBtn,saveBtn,deleteBtn,stopMainID,stopID,stopRoutes,stopNames;
      -
      -                initMap();
      -
      -                function initMap(){
      -
      -                    map = BootstrapMap.create("mapDiv",{
      -                        basemap: "topo",
      -                        center: [-104.99,39.75], // longitude, latitude
      -                        zoom: 15
      -                    });
      -                }
      -            }
      -    );
      -
      -</script>
      -<!-- Bootstrap core JavaScript
      -================================================== -->
      -<!-- Placed at the end of the document so the pages load faster -->
      -<script src="//code.jquery.com/jquery-2.1.3.min.js"></script>
      -<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
      -</body>
      -</html>
      -
      -                        
      -                    
      -
      NOTE: If you aren't building this in the offline repo directory, replace paths with your references.
      -
      -
      -

      Step 2: Configure modal popup

      -

      This initializes and configures the modal popup. Test to make sure map loads and popup displays. - You'll notice the buttons on the popup don't work yet. We'll fix that in the Step 3. - A full working version of this step is included in /demo/samples/editing-step2.html.

      -
      - -
      -                        
      -<!DOCTYPE html>
      -<html>
      -<head>
      -    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      -    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
      -    <title>Offline Features</title>
      -    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
      -    <link rel="stylesheet" href="//js.arcgis.com/3.13/esri/css/esri.css">
      -    <link rel="stylesheet" href="../widgets/modal/css/modal-popup.css">
      -    <link rel="stylesheet" type="text/css" href="http://esri.github.io/bootstrap-map-js/src/css/bootstrapmap.css">
      -    <style>
      -        #mapDiv {
      -            min-height: 500px;
      -            max-height: 1000px;
      -        }
      -
      -        #img-offline-indicator {
      -            padding: 8px;
      -            position: relative; float: right;
      -        }
      -
      -        /* Override mod-popup default */
      -        .mod-popup-stop-input {color: black;}
      -        .span-pending {color: blue; padding-left: 1em;}
      -        .voffset20px { margin-top: 20px; }
      -        .floatRight { float: right}
      -    </style>
      -
      -    <!-- Include a reference to offline.js which detects online/offline conditions -->
      -    <script src="../../vendor/offline/offline.min.js"></script>
      -    <script>
      -        // Set how we pull in custom AMD modules
      -        var path = location.pathname.replace(/[^\/]+$/, '');
      -        var dojoConfig =
      -        {
      -            debug: true,
      -            packages:[
      -                {
      -                    name: "widgets",
      -                    location: path + "../widgets/modal/"
      -                }]
      -        }
      -
      -        // Set the online/offline detection options.
      -        // More info at: http://github.hubspot.com/offline/docs/welcome/
      -        Offline.options = {
      -            checks: {
      -                image: {
      -                    url: function() {
      -                        return 'http://esri.github.io/offline-editor-js/tiny-image.png?_=' +
      -                                (Math.floor(Math.random() * 1000000000));
      -                    }
      -                },
      -                active: 'image'
      -            }
      -        }
      -    </script>
      -
      -    <script src="//js.arcgis.com/3.13/"></script>
      -</head>
      -
      -<body>
      -
      -<div class="container voffset20px">
      -    <div class="row">
      -        <div class="col-xs-8">
      -            <button class="btn btn-success" id="btn-online-offline">Go Offline</button>
      -            <span class="span-pending">Pending Edits <span id="span-pending-edits" class="badge">0</span></span>
      -        </div>
      -        <div class="col-xs-4">
      -            <button id="btn-state" class="btn btn-success btn-large floatRight">
      -                <span id="state-span" class="glyphicon glyphicon-link"> Up</span>
      -            </button>
      -        </div>
      -    </div>
      -    <div class="row voffset20px">
      -        <div class="col-xs-12">
      -            <div id="mapDiv"></div>
      -        </div>
      -    </div>
      -</div>
      -<!-- Stub for modal popup -->
      -<div id="modal-popup"></div>
      -
      -<script>
      -
      -    require([
      -                "esri/map","esri/tasks/query",
      -                "dojo/on","dojo/parser", "esri/renderers/SimpleRenderer",
      -                "esri/symbols/SimpleMarkerSymbol","esri/Color",
      -                "widgets/popup","esri/layers/FeatureLayer",
      -                "//esri.github.com/bootstrap-map-js/src/js/bootstrapmap.js",
      -                "../../dist/offline-edit-src.js",
      -                "dojo/domReady!"],
      -            function(Map,Query,on,parser,SimpleRenderer,SimpleMarkerSymbol,
      -                     Color,ModalPopup,FeatureLayer,BootstrapMap){
      -
      -                var map, popup, editsStore;
      -                var defaultSymbol;
      -                var offlineFeaturesManager;
      -                var btnOnlineOffline, btnState, pendingEdits;
      -                var imgOfflineIndicator;
      -                var closeBtn,saveBtn,deleteBtn,stopMainID,stopID,stopRoutes,stopNames;
      -
      -                initVars();
      -                initMap();
      -
      -                function initMap(){
      -
      -                    map = BootstrapMap.create("mapDiv",{
      -                        basemap: "topo",
      -                        center: [-104.99,39.75], // longitude, latitude
      -                        zoom: 15
      -                    });
      -
      -                    map.on("load",function(evt){
      -                        console.log("Map is loaded. Loading popup...")
      -                        window.setTimeout(function(){
      -                            popup.show();
      -                        },2000);
      -                    });
      -                }
      -
      -                function initVars(){
      -
      -                    editsStore = new O.esri.Edit.EditStore();
      -                    popup = new ModalPopup({animation: true, animationDuration: 1},"modal-popup");
      -                    popup.startup();
      -
      -                    parser.parse();
      -
      -                    // Check if browser state is online or offline
      -                    Offline.check();
      -                    Offline.on('up down', updateState );
      -
      -
      -                    btnOnlineOffline = document.getElementById("btn-online-offline");
      -                    imgOfflineIndicator = document.getElementById("state-span");
      -                    btnState = document.getElementById("btn-state");
      -                    pendingEdits = document.getElementById("span-pending-edits");
      -
      -                    // Modify symbol size based on screen size.
      -                    // Bigger screens get smaller symbols. Smaller screens get larger symbols.
      -                    var width = window.innerWidth
      -                            || document.documentElement.clientWidth
      -                            || document.body.clientWidth;
      -
      -                    var height = window.innerHeight
      -                            || document.documentElement.clientHeight
      -                            || document.body.clientHeight;
      -
      -                    if (height >= 768 || width >= 1024) {
      -                        defaultSymbol= new SimpleMarkerSymbol().setStyle(
      -                                SimpleMarkerSymbol.STYLE_DIAMOND).setColor(
      -                                new Color([255,0,0,0.5])).setSize(20);
      -                    }
      -                    else{
      -                        defaultSymbol= new SimpleMarkerSymbol().setStyle(
      -                                SimpleMarkerSymbol.STYLE_DIAMOND).setColor(
      -                                new Color([255,0,0,0.5])).setSize(35);
      -                    }
      -
      -                    // Variables for modal popup
      -                    closeBtn = document.getElementById("mod-popup-close-btn");
      -                    saveBtn = document.getElementById("mod-popup-save-btn");
      -                    deleteBtn = document.getElementById("mod-popup-delete-btn");
      -                    stopMainID = document.getElementById("stop-main-id");
      -                    stopID = document.getElementById("stop-id");
      -                    stopRoutes = document.getElementById("stop-routes");
      -                    stopNames = document.getElementById("stop-names");
      -
      -                }
      -
      -                function setModalPopupClickListeners(){
      -                    closeBtn.onclick = function(evt){
      -                        hideModalPopup();
      -                    }
      -
      -                    saveBtn.onclick = function(evt) {
      -                        //TO-DO
      -                    }
      -
      -                }
      -
      -                function showModalPopup(graphic){
      -                    popup.graphic = graphic; // assign graphic to modPopup as a property.
      -                    popup.show();
      -                }
      -
      -                function hideModalPopup(){
      -                    popup.hide();
      -                }
      -
      -                // Force feature service offline
      -                function goOnlineOffline(){
      -
      -                    if(btnOnlineOffline.innerHTML == "Go Offline"){
      -                        toggleStateUp(false);
      -                        console.log("Map is offline");
      -                    }
      -                    else{
      -                        toggleStateUp(true);
      -                        console.log("Map is online");
      -                    }
      -                }
      -
      -                // Set the UX to online or offline state
      -                function toggleStateUp(state){
      -                    if(state){
      -                        btnOnlineOffline.innerHTML = "Go Offline";
      -                        offlineFeaturesManager.goOnline();
      -                        imgOfflineIndicator.className = "glyphicon glyphicon-link";
      -                        imgOfflineIndicator.innerHTML = " Up";
      -                        btnState.className = "btn btn-success btn-large floatRight";
      -                    }
      -                    else{
      -                        btnOnlineOffline.innerHTML = "Go Online";
      -                        offlineFeaturesManager.goOffline();
      -                        imgOfflineIndicator.className = "glyphicon glyphicon-thumbs-down";
      -                        imgOfflineIndicator.innerHTML = " Down";
      -                        btnState.className = "btn btn-danger btn-large floatRight";
      -                    }
      -                }
      -
      -                // Automatically set the feature service online or offline.
      -                function updateState(){
      -                    if(Offline.state === 'up'){
      -                        toggleStateUp(true);
      -                    }
      -                    else{
      -                        toggleStateUp(false);
      -                    }
      -                }
      -            }
      -    );
      -
      -</script>
      -<!-- Bootstrap core JavaScript
      -================================================== -->
      -<!-- Placed at the end of the document so the pages load faster -->
      -<script src="//code.jquery.com/jquery-2.1.3.min.js"></script>
      -<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
      -</body>
      -</html>
      -
      -                        
      -                    
      -
      NOTE: If you aren't building this in the offline repo directory, replace paths with your references.
      - -
      - -
      -

      Step 3: Configure offline editing.

      -

      Enable the ability to store features (points, lines and polygons) while offline, and resync features when internet is restored. - A full working version of this step is included in /demo/samples/editing-step3.html.

      -
      - - - -
      - - -
      -
      -
      -                            
      -
      -<!DOCTYPE html>
      -<html>
      -<head>
      -    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      -    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
      -    <title>Offline Features</title>
      -    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
      -    <link rel="stylesheet" href="//js.arcgis.com/3.13/esri/css/esri.css">
      -    <link rel="stylesheet" href="//esri.github.io/bootstrap-map-js/src/css/bootstrapmap.css">
      -    <link rel="stylesheet" href="../widgets/modal/css/modal-popup.css">
      -    <style>
      -        #mapDiv {
      -            min-height: 500px;
      -            max-height: 1000px;
      -        }
      -
      -        #img-offline-indicator {
      -            padding: 8px;
      -            position: relative;
      -            float: right;
      -        }
      -
      -        /* Override mod-popup default */
      -        .mod-popup-stop-input {
      -            color: black;
      -        }
      -
      -        .span-pending {
      -            color: blue;
      -            padding-left: 1em;
      -        }
      -
      -        .voffset20px {
      -            margin-top: 20px;
      -        }
      -
      -        .floatRight {
      -            float: right
      -        }
      -    </style>
      -
      -    <!-- Include a reference to offline.js which detects online/offline conditions -->
      -    <script src="../../vendor/offline/offline.min.js"></script>
      -    <script>
      -        // Set how we pull in custom AMD modules
      -        var path = location.pathname.replace(/[^\/]+$/, '');
      -        var dojoConfig =
      -        {
      -            debug: true,
      -            packages: [
      -                {
      -                    name: "widgets",
      -                    location: path + "../widgets/modal/"
      -                }]
      -        }
      -
      -        // Set the online/offline detection options.
      -        // More info at: http://github.hubspot.com/offline/docs/welcome/
      -        Offline.options = {
      -            checks: {
      -                image: {
      -                    url: function () {
      -                        return 'http://esri.github.io/offline-editor-js/tiny-image.png?_=' +
      -                                (Math.floor(Math.random() * 1000000000));
      -                    }
      -                },
      -                active: 'image'
      -            }
      -        }
      -    </script>
      -
      -    <script src="//js.arcgis.com/3.13/"></script>
      -</head>
      -
      -<body>
      -
      -<div class="container voffset20px">
      -    <div class="row">
      -        <div class="col-xs-8">
      -            <button class="btn btn-success" id="btn-online-offline">Go Offline</button>
      -            <span class="span-pending">Pending Edits <span id="span-pending-edits" class="badge">0</span></span>
      -        </div>
      -        <div class="col-xs-4">
      -            <button id="btn-state" class="btn btn-success btn-large floatRight">
      -                <span id="state-span" class="glyphicon glyphicon-link"> Up</span>
      -            </button>
      -        </div>
      -    </div>
      -    <div class="row voffset20px">
      -        <div class="col-xs-12">
      -            <div id="mapDiv"></div>
      -        </div>
      -    </div>
      -</div>
      -<!-- Stub for modal popup -->
      -<div id="modal-popup"></div>
      -
      -<script>
      -
      -    require([
      -                "esri/map", "esri/tasks/query",
      -                "dojo/on", "dojo/parser", "esri/renderers/SimpleRenderer",
      -                "esri/symbols/SimpleMarkerSymbol", "esri/Color",
      -                "widgets/popup", "esri/layers/FeatureLayer",
      -                "//esri.github.com/bootstrap-map-js/src/js/bootstrapmap.js",
      -                "../../dist/offline-edit-src.js",
      -                "dojo/domReady!"],
      -            function (Map, Query, on, parser, SimpleRenderer, SimpleMarkerSymbol,
      -                      Color, ModalPopup, FeatureLayer, BootstrapMap) {
      -
      -                var map, popup, editsStore;
      -                var defaultSymbol;
      -                var offlineFeaturesManager;
      -                var btnOnlineOffline, btnState, pendingEdits;
      -                var imgOfflineIndicator;
      -                var closeBtn, saveBtn, deleteBtn, stopMainID, stopID, stopRoutes, stopNames;
      -                var busStopFeatureLayer;
      -
      -                initVars();
      -                initMap();
      -
      -                function initMap() {
      -
      -                    map = BootstrapMap.create("mapDiv", {
      -                        basemap: "topo",
      -                        center: [-104.99, 39.75], // longitude, latitude
      -                        zoom: 15
      -                    });
      -
      -                    busStopFeatureLayer = new FeatureLayer("http://services1.arcgis.com/M8KJPUwAXP8jhtnM/arcgis/rest/services/Denver_Bus_Stops/FeatureServer/0", {
      -                        mode: FeatureLayer.MODE_SNAPSHOT,
      -                        outFields: ["OBJECTID", "BSID", "ROUTES", "STOPNAME"]
      -                    });
      -
      -                    //Set the graphics to red boxes to make it easy to click on them
      -                    //on a mobile device.
      -                    busStopFeatureLayer.setRenderer(new SimpleRenderer(defaultSymbol));
      -                    busStopFeatureLayer.on("update-end", function (evt) {
      -
      -                        // Now we can enable the button click listener
      -                        on(btnOnlineOffline, "click", goOnlineOffline);
      -
      -                        initOfflineFeaturesMgr();
      -                        setFeatureLayerClickHandler();
      -                        setModalPopupClickListeners();
      -                    });
      -
      -                    map.addLayer(busStopFeatureLayer);
      -                }
      -
      -                function initVars() {
      -
      -                    editsStore = new O.esri.Edit.EditStore();
      -                    popup = new ModalPopup({animation: true, animationDuration: 1}, "modal-popup");
      -                    popup.startup();
      -
      -                    parser.parse();
      -
      -                    // Check if browser state is online or offline
      -                    Offline.check();
      -                    Offline.on('up down', updateState);
      -
      -
      -                    btnOnlineOffline = document.getElementById("btn-online-offline");
      -                    imgOfflineIndicator = document.getElementById("state-span");
      -                    btnState = document.getElementById("btn-state");
      -                    pendingEdits = document.getElementById("span-pending-edits");
      -
      -                    // Modify symbol size based on screen size.
      -                    // Bigger screens get smaller symbols. Smaller screens get larger symbols.
      -                    var width = window.innerWidth
      -                            || document.documentElement.clientWidth
      -                            || document.body.clientWidth;
      -
      -                    var height = window.innerHeight
      -                            || document.documentElement.clientHeight
      -                            || document.body.clientHeight;
      -
      -                    if (height >= 768 || width >= 1024) {
      -                        defaultSymbol = new SimpleMarkerSymbol().setStyle(
      -                                SimpleMarkerSymbol.STYLE_DIAMOND).setColor(
      -                                new Color([255, 0, 0, 0.5])).setSize(20);
      -                    }
      -                    else {
      -                        defaultSymbol = new SimpleMarkerSymbol().setStyle(
      -                                SimpleMarkerSymbol.STYLE_DIAMOND).setColor(
      -                                new Color([255, 0, 0, 0.5])).setSize(35);
      -                    }
      -
      -                    // Variables for modal popup
      -                    closeBtn = document.getElementById("mod-popup-close-btn");
      -                    saveBtn = document.getElementById("mod-popup-save-btn");
      -                    deleteBtn = document.getElementById("mod-popup-delete-btn");
      -                    stopMainID = document.getElementById("stop-main-id");
      -                    stopID = document.getElementById("stop-id");
      -                    stopRoutes = document.getElementById("stop-routes");
      -                    stopNames = document.getElementById("stop-names");
      -
      -                }
      -
      -                /**
      -                 * ************************************
      -                 * OFFLINE FEATURE SERVICE HANDLER CODE
      -                 * ************************************
      -                 */
      -
      -                function initOfflineFeaturesMgr() {
      -                    offlineFeaturesManager = new O.esri.Edit.OfflineFeaturesManager();
      -
      -                    // IMPORTANT!!!
      -                    // A proxy page may be required to upload attachments.
      -                    // If you are using a CORS enabled server you may be able to set the proxyPath to null.
      -                    // Refer to "Using the Proxy Page" for more information:
      -                    //https://developers.arcgis.com/en/javascript/jshelp/ags_proxy.html
      -                    offlineFeaturesManager.proxyPath = null;
      -
      -                    // IMPORTANT!!!
      -                    // This tells the database which graphic.attribute property to use as a unique identifier
      -                    // You can lok this information up in your feature service directory under the "Fields" category.
      -                    // Example: http://services1.arcgis.com/M8KJPUwAXP8jhtnM/arcgis/rest/services/Denver_Bus_Stops/FeatureServer/0
      -                    offlineFeaturesManager.DB_UID = "FID";
      -
      -                    offlineFeaturesManager.on(offlineFeaturesManager.events.EDITS_ENQUEUED, updatePendingEditStatus);
      -                    offlineFeaturesManager.on(offlineFeaturesManager.events.EDITS_SENT, updatePendingEditStatus);
      -                    offlineFeaturesManager.on(offlineFeaturesManager.events.ALL_EDITS_SENT, updatePendingEditStatus);
      -
      -                    offlineFeaturesManager.on(offlineFeaturesManager.events.EDITS_ENQUEUED_ERROR, function(errorsArray){
      -                        alert("There was an error attempting to write to the database: " + JSON.stringify(errorsArray));
      -                    });
      -
      -                    offlineFeaturesManager.extend(busStopFeatureLayer, function (success, error) {
      -                        if (success) {
      -                            console.log("offlineFeaturesManager initialized.");
      -
      -                            Offline.check();
      -                            Offline.on('up down', updateState);
      -                        }
      -                        else {
      -                            alert("Unable to enable feature layer for offline usage. " + error);
      -                        }
      -                    });
      -                }
      -
      -                // Display modal popup when someone clicks on a feature
      -                // and load the fields with data from the feature service.
      -                function setFeatureLayerClickHandler() {
      -                    busStopFeatureLayer.on("click", function (evt) {
      -
      -                        showModalPopup(evt.graphic);
      -                        var atts = evt.graphic.attributes;
      -                        stopID.value = atts.BSID;
      -                        stopMainID.value = atts.FID;
      -                        stopNames.value = atts.STOPNAME;
      -                        stopRoutes.value = atts.ROUTES;
      -
      -                    }.bind(this));
      -                }
      -
      -                function updatePendingEditStatus() {
      -                    busStopFeatureLayer.pendingEditsCount(function(count){
      -                        pendingEdits.innerHTML = count;
      -                    });
      -                }
      -
      -
      -                function setModalPopupClickListeners() {
      -                    closeBtn.onclick = function (evt) {
      -                        hideModalPopup();
      -                    };
      -
      -                    saveBtn.onclick = function (evt) {
      -                        popup.graphic.attributes.ROUTES = stopRoutes.value;
      -                        popup.graphic.attributes.STOPNAME = stopNames.value;
      -
      -                        busStopFeatureLayer.applyEdits(null, [popup.graphic], null, function (result) {
      -                                    console.log("Successfully saved changes to: " +
      -                                    popup.graphic.attributes.STOPNAME);
      -                                    hideModalPopup();
      -                                },
      -                                function (err) {
      -                                    alert("There was a problem while trying to save: " +
      -                                    popup.graphic.attributes.STOPNAME);
      -                                })
      -                    };
      -
      -                    deleteBtn.onclick = function (evt) {
      -                        busStopFeatureLayer.applyEdits(null, null, [popup.graphic], function (result) {
      -                                    console.log("Successfully deleted: " + popup.graphic.attributes.STOPNAME);
      -                                    hideModalPopup();
      -                                },
      -                                function (err) {
      -                                    alert("There was a problem while trying to delete: " +
      -                                    popup.graphic.attributes.STOPNAME);
      -                                })
      -                    }
      -
      -                }
      -
      -                function showModalPopup(graphic) {
      -                    popup.graphic = graphic; // assign graphic to modPopup as a property.
      -                    popup.show();
      -                }
      -
      -                function hideModalPopup() {
      -                    popup.hide();
      -                }
      -
      -                /**
      -                 * ************************************
      -                 * GO OFFLINE/ONLINE HANDLER CODE
      -                 * ************************************
      -                 */
      -
      -                // Force feature service offline
      -                function goOnlineOffline() {
      -
      -                    if (btnOnlineOffline.innerHTML == "Go Offline") {
      -                        toggleStateUp(false);
      -                        console.log("Map is offline");
      -                    }
      -                    else {
      -                        toggleStateUp(true);
      -                        console.log("Map is online");
      -                    }
      -                }
      -
      -                // Set the UX to online or offline state
      -                function toggleStateUp(state) {
      -                    if (state) {
      -                        offlineFeaturesManager.goOnline();
      -                        btnOnlineOffline.innerHTML = "Go Offline";
      -                        imgOfflineIndicator.className = "glyphicon glyphicon-link";
      -                        imgOfflineIndicator.innerHTML = " Up";
      -                        btnState.className = "btn btn-success btn-large floatRight";
      -                    }
      -                    else {
      -                        offlineFeaturesManager.goOffline();
      -                        btnOnlineOffline.innerHTML = "Go Online";
      -                        imgOfflineIndicator.className = "glyphicon glyphicon-thumbs-down";
      -                        imgOfflineIndicator.innerHTML = " Down";
      -                        btnState.className = "btn btn-danger btn-large floatRight";
      -                    }
      -                }
      -
      -                // Automatically set the feature service online or offline.
      -                function updateState() {
      -                    if (Offline.state === 'up') {
      -                        toggleStateUp(true);
      -                    }
      -                    else {
      -                        toggleStateUp(false);
      -                    }
      -                }
      -            }
      -    );
      -
      -</script>
      -<!-- Bootstrap core JavaScript
      -================================================== -->
      -<!-- Placed at the end of the document so the pages load faster -->
      -<script src="//code.jquery.com/jquery-2.1.3.min.js"></script>
      -<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
      -</body>
      -</html>
      -
      -                            
      -                        
      -
      NOTE: If you aren't building this in the offline repo directory, replace paths with your references.
      -
      - -
      -
      -
      - - Pending Edits 0 -
      -
      - -
      -
      -
      -
      -
      -
      -
      - -
      -
      -
      -
      - -
      -
      -
      -
      -
      - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/demo/getstarted-tiles.html b/demo/getstarted-tiles.html deleted file mode 100644 index 5ba871b6..00000000 --- a/demo/getstarted-tiles.html +++ /dev/null @@ -1,785 +0,0 @@ - - - - - - - - - Offline-editor-js - - - - - - - - - - - - - - - - - - - - - - - -
      -
      -

      Getting Started with Tiles

      -

      Basic steps for working with tiled base map services for offline.

      - -
      -
      - -
      - -
      -
      - - - -
      -
      -

      Step 1: Fill in the basics

      -

      Add the basic library references. Then test to make sure map loads.

      -
      -
      -                        
      -<!DOCTYPE html>
      -<html>
      -<head>
      -    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      -    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
      -    <title>Offline Tiles</title>
      -
      -    <!-- Bootstrap core CSS -->
      -    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
      -
      -    <link rel="stylesheet" href="http://js.arcgis.com/3.11/esri/css/esri.css">
      -    <link rel="stylesheet" type="text/css" href="http://esri.github.io/bootstrap-map-js/src/css/bootstrapmap.css">
      -    <style>
      -        #mapDiv {
      -            min-height: 500px;
      -            max-height: 1000px;
      -        }
      -
      -        body {
      -            background-color: #ffffff;
      -            overflow: hidden;
      -            font-family: "Trebuchet MS";
      -        }
      -
      -        .floatRight {float: right;}
      -        .container { padding: 20px;}
      -    </style>
      -
      -    <!-- Include a reference to offline.js which detects online/offline conditions -->
      -    <script src="../vendor/offline/offline.min.js"></script>
      -    <script>
      -        // Set the online/offline detection options.
      -        // More info at: http://github.hubspot.com/offline/docs/welcome/
      -        Offline.options = {
      -            checks: {
      -                image: {
      -                    url: function() {
      -                        return 'http://esri.github.io/offline-editor-js/tiny-image.png?_=' +
      -                                (Math.floor(Math.random() * 1000000000));
      -                    }
      -                },
      -                active: 'image'
      -            }
      -        }
      -    </script>
      -
      -    <!-- Include a reference to IndexedDBShim for library to work on Safari 7.x -->
      -    <script src="../vendor/IndexedDBShim/dist/IndexedDBShim.js"></script>
      -
      -    <script src="http://js.arcgis.com/3.11/"></script>
      -</head>
      -
      -<body>
      -<div class="row">
      -    <div class="col-xs-12">
      -        <div id="mapDiv"></div>
      -    </div>
      -</div>
      -
      -<script>
      -
      -    // Make sure to reference the tiles library within the require statement!
      -    require(["esri/map","dojo/on","//esri.github.com/bootstrap-map-js/src/js/bootstrapmap.js","../dist/offline-tiles-advanced-min.js", "dojo/domReady!"],
      -        function(Map,on,Bootstrapmap) {
      -
      -        // Initialize our map to be responsive
      -        var map = Bootstrapmap.create("mapDiv",{
      -            basemap: "topo",
      -            center: [-122.45, 37.75], // longitude, latitude
      -            zoom: 15
      -        });
      -
      -    });
      -</script>
      -
      -<!-- Bootstrap core JavaScript
      -================================================== -->
      -<!-- Placed at the end of the document so the pages load faster -->
      -<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      -<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
      -</body>
      -</html>
      -
      -                        
      -                    
      -
      NOTE: Replace paths with your references. Or build your app in the /demo directory
      -
      -
      -

      Step 2: Configure tiled basemap to work offline

      -

      This initializes the offline-editor-js library. Test to make sure map loads.

      -
      - -
      -                        
      -<!DOCTYPE html>
      -<html>
      -<head>
      -    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      -    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
      -    <title>Offline Tiles</title>
      -
      -    <!-- Bootstrap core CSS -->
      -    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
      -
      -    <link rel="stylesheet" href="http://js.arcgis.com/3.11/esri/css/esri.css">
      -    <link rel="stylesheet" type="text/css" href="http://esri.github.io/bootstrap-map-js/src/css/bootstrapmap.css">
      -    <style>
      -        #mapDiv {
      -            min-height: 500px;
      -            max-height: 1000px;
      -        }
      -
      -        body {
      -            background-color: #ffffff;
      -            overflow: hidden;
      -            font-family: "Trebuchet MS";
      -        }
      -
      -       .floatRight {float: right;}
      -        .container { padding: 20px;}
      -    </style>
      -
      -    <!-- Include a reference to offline.js which detects online/offline conditions -->
      -    <script src="../vendor/offline/offline.min.js"></script>
      -    <script>
      -        // Set the online/offline detection options.
      -        // More info at: http://github.hubspot.com/offline/docs/welcome/
      -        Offline.options = {
      -            checks: {
      -                image: {
      -                    url: function() {
      -                        return 'http://esri.github.io/offline-editor-js/tiny-image.png?_=' +
      -                                (Math.floor(Math.random() * 1000000000));
      -                    }
      -                },
      -                active: 'image'
      -            }
      -        }
      -    </script>
      -
      -    <!-- Include a reference to IndexedDBShim for library to work on Safari 7.x -->
      -    <script src="../vendor/IndexedDBShim/dist/IndexedDBShim.js"></script>
      -
      -    <script src="http://js.arcgis.com/3.11/"></script>
      -</head>
      -
      -<body>
      -<div class="row">
      -    <div class="col-xs-12">
      -        <div id="mapDiv"></div>
      -    </div>
      -</div>
      -
      -<script>
      -
      -    // Make sure to reference the tiles library within the require statement!
      -    require(["esri/map","dojo/on","//esri.github.com/bootstrap-map-js/src/js/bootstrapmap.js","../dist/offline-tiles-advanced-min.js", "dojo/domReady!"],
      -        function(Map,on,Bootstrapmap) {
      -
      -        // Check if browser state is online or offline
      -        Offline.check();
      -        Offline.on('up down', updateState );
      -
      -        // Initialize our map to be responsive
      -        var map = Bootstrapmap.create("mapDiv",{
      -            //basemap: "topo", // comment out this basemap!
      -            center: [-122.45, 37.75], // longitude, latitude
      -            zoom: 15
      -        });
      -
      -        // Now we initialize a topo tiled basemap service to be offline-enabled.
      -        var tileLayer = O.esri.Tiles.OfflineTileEnablerLayer(
      -                "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer",
      -                function(evt){
      -                    console.log("Offline tile lib enabled. App is: " + Offline.state);
      -                },
      -                true);
      -
      -        // Add our offline tile layer to the map instead of using the default basemap!
      -        map.addLayer(tileLayer);
      -
      -        // Set the tileLayer online or offline.
      -        // When set to offline, the map will look for tiles in the local tiles database
      -        function updateState(){
      -            if(Offline.state === 'up'){
      -                if(typeof tileLayer != "undefined") tileLayer.goOnline();
      -            }
      -            else{
      -                if(typeof tileLayer != "undefined") tileLayer.goOffline();
      -            }
      -        }
      -
      -    });
      -</script>
      -
      -<!-- Bootstrap core JavaScript
      -================================================== -->
      -<!-- Placed at the end of the document so the pages load faster -->
      -<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      -<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
      -</body>
      -</html>
      -
      -                        
      -                    
      -
      NOTE: Replace paths with your references. Or build your app in the /demo directory
      - -
      - -
      -

      Step 3: Configure tiles download.

      -

      Enable the ability to download tiles as well the ability to toggle online and offline.

      -
      - - - -
      - - -
      -
      -
      -                            
      -
      -<!DOCTYPE html>
      -<html>
      -<head>
      -    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      -    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
      -    <title>Offline Tiles</title>
      -
      -    <!-- Bootstrap core CSS -->
      -    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
      -
      -    <link rel="stylesheet" href="http://js.arcgis.com/3.11/esri/css/esri.css">
      -    <link rel="stylesheet" type="text/css" href="http://esri.github.io/bootstrap-map-js/src/css/bootstrapmap.css">
      -    <style>
      -        #mapDiv {
      -            min-height: 500px;
      -            max-height: 1000px;
      -        }
      -
      -        body {
      -            background-color: #ffffff;
      -            overflow: hidden;
      -            font-family: "Trebuchet MS";
      -        }
      -
      -        .floatRight { float: right;}
      -        .container { padding: 20px;}
      -    </style>
      -
      -    <!-- Include a reference to offline.js which detects online/offline conditions -->
      -    <script src="../vendor/offline/offline.min.js"></script>
      -    <script>
      -        // Set the online/offline detection options.
      -        // More info at: http://github.hubspot.com/offline/docs/welcome/
      -        Offline.options = {
      -            checks: {
      -                image: {
      -                    url: function() {
      -                        return 'http://esri.github.io/offline-editor-js/tiny-image.png?_=' +
      -                                (Math.floor(Math.random() * 1000000000));
      -                    }
      -                },
      -                active: 'image'
      -            }
      -        }
      -    </script>
      -
      -    <!-- Include a reference to IndexedDBShim for library to work on Safari 7.x -->
      -    <script src="../vendor/IndexedDBShim/dist/IndexedDBShim.js"></script>
      -
      -    <script src="http://js.arcgis.com/3.11/"></script>
      -</head>
      -
      -<body>
      -
      -<!-- Our buttons and online/offline indicator -->
      -<div class="container">
      -    <div class="row">
      -        <div class="col-xs-10">
      -            <div class="form form-group btn-group" data-toggle="buttons">
      -                <button class="btn btn-success" id="btn-get-tiles">1. Download Tiles</button>
      -                <button class="btn btn-success" disabled id="btn-online-offline">2. Go Offline</button>
      -                <button class="btn btn-success" disabled id="btn-pan-left">3. Pan left</button>
      -            </div>
      -        </div>
      -        <div class="col-xs-2">
      -            <!-- this indicates whether app is offline (down) or online (up) -->
      -            <button id="btn-state" class="btn btn-success btn-large floatRight">
      -                <span id="state-span" class="glyphicon glyphicon-link"> Up</span>
      -            </button>
      -        </div>
      -    </div>
      -    <div class="row">
      -        <div class="col-xs-12">
      -            <div id="mapDiv"></div>
      -        </div>
      -    </div>
      -</div>
      -
      -<script>
      -
      -    // Make sure to reference the tiles library within the require statement!
      -    require(["esri/map","dojo/on","//esri.github.com/bootstrap-map-js/src/js/bootstrapmap.js",
      -        "../dist/offline-tiles-advanced-min.js", "dojo/domReady!"],
      -        function(Map,on,Bootstrapmap){
      -
      -            var map,basemapLayer;
      -
      -            // Check if browser state is online or offline
      -            Offline.check();
      -            Offline.on('up down', updateState );
      -
      -            // For cancelling the download of tiles
      -            var _wantToCancel = false;
      -            var _downloadState = "downloaded";
      -
      -            // Set up min and max boundaries for retrieving tiles
      -            var minZoomAdjust = -1, maxZoomAdjust = 1;
      -
      -            // Set up button click listeners.
      -            var btnGetTiles = document.getElementById("btn-get-tiles");
      -            var btnOnlineOffline = document.getElementById("btn-online-offline");
      -            var btnPanLeft = document.getElementById("btn-pan-left");
      -
      -            on(btnGetTiles,"click",downloadTiles);
      -            on(btnOnlineOffline,"click",goOnlineOffline);
      -            on(btnPanLeft,"click",panLeft);
      -
      -            var imgOfflineIndicator = document.getElementById("state-span");
      -            var btnState = document.getElementById("btn-state");
      -
      -            showMap();
      -
      -            function showMap(){
      -
      -                // Initialize our map to be responsive
      -                map = Bootstrapmap.create("mapDiv",{
      -                    //basemap: "topo", // comment out this basemap!
      -                    center: [-122.45, 37.75], // longitude, latitude
      -                    zoom: 15
      -                });
      -
      -                // Now we initialize the basemap to be offline-enabled. This is out new basemap.
      -                basemapLayer = O.esri.Tiles.OfflineTileEnablerLayer(
      -                        "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer",
      -                        function(evt){
      -                            console.log("Offline tile lib enabled. App is: " + Offline.state);
      -                        },
      -                        true);
      -
      -                // Add our offline tile layer to the map instead of using the default basemap!
      -                map.addLayer(basemapLayer);
      -            }
      -
      -            function downloadTiles(){
      -
      -                if(_downloadState == "downloading"){
      -                    _wantToCancel = true;
      -                }
      -                else{
      -                    _wantToCancel = false;
      -
      -                    // First delete any existing tiles from database
      -                    basemapLayer.deleteAllTiles(function(success,err){
      -                        var zoom = basemapLayer.getMinMaxLOD(minZoomAdjust,maxZoomAdjust);
      -
      -                        // Now download tiles
      -                        basemapLayer.prepareForOffline(zoom.min, zoom.max, map.extent, function(progress){
      -                            console.log("downloading tiles...");
      -
      -                            if(progress.hasOwnProperty("countNow")){
      -                                var percent = Math.floor(progress.countNow / progress.countMax * 100);
      -                                btnGetTiles.innerHTML = 'Saving to phone ' + percent + "% - Tap to Cancel";
      -                            }
      -
      -                            if( progress.finishedDownloading )
      -                            {
      -                                btnGetTiles.innerHTML = "Saving to phone 100% - Tap to Cancel";
      -
      -                                if( progress.cancelRequested )
      -                                {
      -                                    alert("Tile download was cancelled");
      -                                    _downloadState = "cancelled";
      -                                }
      -                                else
      -                                {
      -                                    alert("Tile download complete");
      -                                    _downloadState = "downloaded";
      -                                    btnOnlineOffline.disabled = false;
      -                                }
      -
      -                                btnGetTiles.innerHTML = '1. Download Tiles';
      -                            }
      -                            return _wantToCancel; //determines if a cancel request has been issued
      -                        });
      -
      -                        _downloadState = "downloading";
      -
      -                    });
      -                }
      -            }
      -
      -            // Force the tileLayer between online and offline
      -            function goOnlineOffline(){
      -
      -                btnPanLeft.disabled = false;
      -
      -                if(btnOnlineOffline.innerHTML == "2. Go Offline"){
      -                    toggleStateUp(false);
      -                    console.log("Map is offline");
      -                }
      -                else{
      -                    toggleStateUp(true);
      -                    console.log("Map is online");
      -                }
      -            }
      -
      -            function toggleStateUp(state){
      -                if(state){
      -                    btnOnlineOffline.innerHTML = "2. Go Offline";
      -                    basemapLayer.goOnline();
      -                    imgOfflineIndicator.className = "glyphicon glyphicon-link";
      -                    imgOfflineIndicator.innerHTML = " Up";
      -                    btnState.className = "btn btn-success btn-large floatRight";
      -                }
      -                else{
      -                    btnOnlineOffline.innerHTML = "2. Go Online";
      -                    basemapLayer.goOffline();
      -                    imgOfflineIndicator.className = "glyphicon glyphicon-thumbs-down";
      -                    imgOfflineIndicator.innerHTML = " Down";
      -                    btnState.className = "btn btn-danger btn-large floatRight";
      -                }
      -            }
      -
      -            // Set the ArcGIS.com map online or offline.
      -            // When set offline it will look for tiles in the tiles database
      -            function updateState(){
      -                if(Offline.state === 'up'){
      -                    if(typeof basemapLayer != "undefined") basemapLayer.goOnline();
      -                    toggleStateUp(true);
      -                }
      -                else{
      -                    if(typeof basemapLayer != "undefined") basemapLayer.goOffline();
      -                    toggleStateUp(false);
      -                }
      -            }
      -
      -            // Pan left when "offline" to view only tiles that have been stored locally
      -            function panLeft(){
      -                map.panLeft();
      -            }
      -
      -    });
      -</script>
      -
      -<!-- Bootstrap core JavaScript
      -================================================== -->
      -<!-- Placed at the end of the document so the pages load faster -->
      -<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      -<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
      -</body>
      -</html>
      -
      -                            
      -                        
      -
      NOTE: Replace paths with your references. Or build your app in the /demo directory
      -
      - -
      -
      -
      -
      - - - -
      -
      -
      - - -
      -
      -
      -
      -
      -
      -
      - -
      -
      -
      -
      - -
      -
      -
      -
      -
      - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/demo/getstarted-tpk.html b/demo/getstarted-tpk.html deleted file mode 100644 index c86507fe..00000000 --- a/demo/getstarted-tpk.html +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - - - - Offline-editor-js - - - - - - - - - - - - - - - - - - - - - - - -
      -
      -

      Getting Started with TPKs

      -

      Basic steps for working with TPK packages for offline.

      - -
      -
      - -
      - -
      -
      - - - -
      -
      -

      Step 1: Fill in the basics

      -

      Add the basic library references and CSS. Then test to make sure application loads. - There won't be a map to display just yet, you'll only see the header bar.

      -
      -
      -                        
      -<!DOCTYPE html>
      -<html>
      -<head>
      -    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      -    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
      -    <title>Offline TPK</title>
      -    <link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" media="screen">
      -    <link rel="stylesheet" href="http://js.arcgis.com/3.11/esri/css/esri.css"">
      -    <link rel="stylesheet" type="text/css" href="http://esri.github.io/bootstrap-map-js/src/css/bootstrapmap.css">
      -    <style>
      -        #mapDiv {
      -            min-height: 300px;
      -            max-height: 1000px;
      -        }
      -        .container { padding: 20px;}
      -    </style>
      -
      -    <!-- Include a reference to IndexedDBShim for library to work on Safari 7.x -->
      -    <script src="../vendor/IndexedDBShim/dist/IndexedDBShim.js"></script>
      -
      -    <script src="http://js.arcgis.com/3.11/"></script>
      -</head>
      -
      -<body>
      -
      -<div class="container">
      -    <div class="row">
      -        <div class="col-lg-12">
      -            <div class="form form-group input-group">
      -                <input id="url-input" type="text" class="form-control"
      -                            value="../samples/tpks/Beirut.zip">
      -            <span class="input-group-btn">
      -                <button id="url-btn" class="btn btn-success" type="button">Go!</button>
      -            </span>
      -            </div>
      -        </div>
      -    </div>
      -    <div class="row">
      -        <div class="col-xs-12">
      -            <div id="mapDiv"></div>
      -        </div>
      -    </div>
      -</div>
      -
      -<script>
      -
      -    // Make sure to reference the tpk library within the require statement!
      -    require([
      -        "esri/map",
      -        "dojo/on",
      -        "//esri.github.com/bootstrap-map-js/src/js/bootstrapmap.js",
      -        "../dist/offline-tpk-src.js", "dojo/domReady!"],
      -            function(Map,on,BootstrapMap) {
      -
      -                var map, tpkLayer;
      -
      -                var url = document.getElementById("url-input");
      -                var urlInputBtn = document.getElementById("url-btn");
      -
      -            }
      -    );
      -</script>
      -<!-- Bootstrap core JavaScript
      -================================================== -->
      -<!-- Placed at the end of the document so the pages load faster -->
      -<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      -<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
      -</body>
      -</html>
      -
      -                        
      -                    
      -
      NOTE: Replace paths with your references.
      -
      -
      -

      Step 2: Retrieve TPK.

      -

      Download and unzip the TPK. You should get an alert when TPK is fully downloaded.

      -

      NOTE: If you have a TPK file you will have to change its type to .zip for the browser to recognize it.

      -
      - -
      -                        
      -<!DOCTYPE html>
      -<html>
      -<head>
      -    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      -    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
      -    <title>Offline TPK</title>
      -    <link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" media="screen">
      -    <link rel="stylesheet" href="http://js.arcgis.com/3.11/esri/css/esri.css">
      -    <link rel="stylesheet" type="text/css" href="http://esri.github.io/bootstrap-map-js/src/css/bootstrapmap.css">
      -    <style>
      -        #mapDiv {
      -            min-height: 300px;
      -            max-height: 1000px;
      -        }
      -        .container { padding: 20px;}
      -    </style>
      -
      -    <!-- Include a reference to IndexedDBShim for library to work on Safari 7.x -->
      -    <script src="../vendor/IndexedDBShim/dist/IndexedDBShim.js"></script>
      -
      -    <script src="http://js.arcgis.com/3.11/"></script>
      -</head>
      -
      -<body>
      -
      -<div class="container">
      -    <div class="row">
      -        <div class="col-lg-12">
      -            <div class="form form-group input-group">
      -                <input id="url-input" type="text" class="form-control"
      -                       value="../samples/tpks/Beirut.zip">
      -            <span class="input-group-btn">
      -                <button id="url-btn" class="btn btn-success" type="button">Go!</button>
      -            </span>
      -            </div>
      -        </div>
      -    </div>
      -    <div class="row">
      -        <div class="col-xs-12">
      -            <div id="mapDiv"></div>
      -        </div>
      -    </div>
      -</div>
      -
      -<script>
      -
      -    // Make sure to reference the tpk library within the require statement!
      -    require([
      -        "esri/map",
      -        "dojo/on",
      -        "//esri.github.com/bootstrap-map-js/src/js/bootstrapmap.js",
      -        "../dist/offline-tpk-src.js", "dojo/domReady!"],
      -            function(Map,on,BootstrapMap) {
      -
      -                var map, tpkLayer;
      -
      -                var url = document.getElementById("url-input");
      -                var urlInputBtn = document.getElementById("url-btn");
      -                urlInputBtn.onclick = function(){
      -                    getTPK();
      -                };
      -
      -                // Retrieve the TPK file via an HTTP request
      -                function getTPK(){
      -                    urlInputBtn.innerHTML = "Get file via url";
      -
      -                    var xhrRequest = new XMLHttpRequest();
      -                    xhrRequest.open("GET", url.value, true);
      -                    xhrRequest.responseType = "blob";
      -                    xhrRequest.onprogress = function(evt){
      -                        var percent = (parseFloat(evt.loaded / evt.totalSize) * 100).toFixed(0);
      -                        urlInputBtn.innerHTML = "Get file via url " + percent + "%";
      -                        console.log("Begin downloading remote tpk file...")
      -                    }
      -
      -                    xhrRequest.error = function(err){console.log("ERROR")}
      -
      -                    xhrRequest.onload = function(oEvent) {
      -                        if(this.status == 200) {
      -                            console.log("Remote tpk download finished.")
      -                            zipParser(this.response);
      -                        }
      -                        else{
      -                            alert("There was a problem loading the file. " + this.status + ": " + this.statusText )
      -                        }
      -                    };
      -
      -                    xhrRequest.send();
      -                }
      -
      -                // Parse the zip file contents into a zip.Entries object
      -                function zipParser(blob){
      -
      -                    O.esri.zip.createReader(new O.esri.zip.BlobReader(blob), function (zipReader) {
      -                        zipReader.getEntries(function (entries) {
      -                            if(entries) alert("TPK downloaded and unzipped!");
      -                            zipReader.close(function(evt){
      -                                console.log("Done reading zip file.")
      -                            })
      -                        }, function (err) {
      -                            alert("There was a problem reading the file!: " + err);
      -                        })
      -                    })
      -                }
      -
      -            }
      -    );
      -</script>
      -<!-- Bootstrap core JavaScript
      -================================================== -->
      -<!-- Placed at the end of the document so the pages load faster -->
      -<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      -<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
      -</body>
      -</html>
      -
      -                        
      -                    
      -
      NOTE: Replace paths with your references.
      - -
      - -
      -

      Step 3: Display TPK tiles.

      -

      In this step we hand the zip file entries over to TPKLayer to inflate the map.

      -
      - - - -
      - - -
      -
      -
      -                            
      -
      -<!DOCTYPE html>
      -<html>
      -<head>
      -    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      -    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
      -    <title>Offline TPK</title>
      -    <link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" media="screen">
      -    <link rel="stylesheet" href="http://js.arcgis.com/3.11/esri/css/esri.css">
      -    <link rel="stylesheet" type="text/css" href="http://esri.github.io/bootstrap-map-js/src/css/bootstrapmap.css">
      -    <style>
      -        #mapDiv {
      -            min-height: 300px;
      -            max-height: 1000px;
      -        }
      -        .container { padding: 20px;}
      -    </style>
      -
      -    <!-- Include a reference to IndexedDBShim for library to work on Safari 7.x -->
      -    <script src="../vendor/IndexedDBShim/dist/IndexedDBShim.js"></script>
      -
      -    <script src="http://js.arcgis.com/3.11/"></script>
      -</head>
      -
      -<body>
      -
      -<div class="container">
      -    <div class="row">
      -        <div class="col-lg-12">
      -            <div class="form form-group input-group">
      -                <input id="url-input" type="text" class="form-control"
      -                       value="../samples/tpks/Beirut.zip">
      -            <span class="input-group-btn">
      -                <button id="url-btn" class="btn btn-success" type="button">Go!</button>
      -            </span>
      -            </div>
      -        </div>
      -    </div>
      -    <div class="row">
      -        <div class="col-xs-12">
      -            <div id="mapDiv"></div>
      -        </div>
      -    </div>
      -</div>
      -
      -<script>
      -
      -    // Make sure to reference the tpk library within the require statement!
      -    require([
      -        "esri/map",
      -        "dojo/on",
      -        "//esri.github.com/bootstrap-map-js/src/js/bootstrapmap.js",
      -        "../dist/offline-tpk-src.js", "dojo/domReady!"],
      -            function(Map,on,BootstrapMap) {
      -
      -                var map, tpkLayer;
      -
      -                var url = document.getElementById("url-input");
      -                var urlInputBtn = document.getElementById("url-btn");
      -                urlInputBtn.onclick = function(){
      -                    getTPK();
      -                };
      -
      -                // Retrieve the TPK file via an HTTP request
      -                function getTPK(){
      -                    urlInputBtn.innerHTML = "Get file via url";
      -
      -                    var xhrRequest = new XMLHttpRequest();
      -                    xhrRequest.open("GET", url.value, true);
      -                    xhrRequest.responseType = "blob";
      -                    xhrRequest.onprogress = function(evt){
      -                        var percent = (parseFloat(evt.loaded / evt.totalSize) * 100).toFixed(0);
      -                        urlInputBtn.innerHTML = "Get file via url " + percent + "%";
      -                        console.log("Begin downloading remote tpk file...")
      -                    }
      -
      -                    xhrRequest.error = function(err){console.log("ERROR")}
      -
      -                    xhrRequest.onload = function(oEvent) {
      -                        if(this.status == 200) {
      -                            console.log("Remote tpk download finished.")
      -                            zipParser(this.response);
      -                        }
      -                        else{
      -                            alert("There was a problem loading the file. " + this.status + ": " + this.statusText )
      -                        }
      -                    };
      -
      -                    xhrRequest.send();
      -                }
      -
      -                // Parse the zip file contents into a zip.Entries object
      -                function zipParser(blob){
      -
      -                    O.esri.zip.createReader(new O.esri.zip.BlobReader(blob), function (zipReader) {
      -                        zipReader.getEntries(function (entries) {
      -                            initMap(entries);
      -                            //if(entries)alert("TPK downloaded and unzipped!");
      -                            zipReader.close(function(evt){
      -                                console.log("Done reading zip file.")
      -                            })
      -                        }, function (err) {
      -                            alert("There was a problem reading the file!: " + err);
      -                        })
      -                    })
      -                }
      -
      -                // Initialize the Map and the TPKLayer
      -                function initMap(entries){
      -
      -                    map = BootstrapMap.create("mapDiv",{});
      -
      -                    tpkLayer = new O.esri.TPK.TPKLayer();
      -                    tpkLayer.on("progress", function (evt) {
      -                        console.log("TPK loading...");
      -                    })
      -                    tpkLayer.extend(entries);
      -
      -                    map.addLayer(tpkLayer);
      -                }
      -
      -            }
      -    );
      -</script>
      -<!-- Bootstrap core JavaScript
      -================================================== -->
      -<!-- Placed at the end of the document so the pages load faster -->
      -<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      -<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
      -</body>
      -</html>
      -
      -                            
      -                        
      -
      NOTE: Replace paths with your references. This sample may look different than our live sample.
      -
      - -
      -
      -
      -
      - - - - -
      -
      -
      -
      -
      -
      -
      -
      - -
      - -
      -
      - -
      -
      -
      -
      -
      - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/demo/getstarted.html b/demo/getstarted.html deleted file mode 100644 index 90c57436..00000000 --- a/demo/getstarted.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - Offline-editor-js - - - - - - - - - - - - - - - - - - - - - - - -
      -
      -

      Getting Started Samples

      -

      Basic responsive samples on how to work with the ArcGIS API for JavaScript while offline.

      - -
      -
      - -
      - - - -
      -
      -
      -

      Fork or clone offline-editor-js

      -
      -
      -

      Here are the important directories to know:

      -
        -
      • \dist - minified library files and concatenated source (for debugging).
      • -
      • \samples - more examples that demonstrate the library's functionality.
      • -
      • \vendor - contains IndexedDBShim and offline.js helper libraries
      • -
      -
      - -
      -
      -
      - -
      - - - - - - - - - - - - - \ No newline at end of file diff --git a/demo/header.html b/demo/header.html index 6c3b445a..f243abeb 100644 --- a/demo/header.html +++ b/demo/header.html @@ -1,14 +1,14 @@ - +
      -
      -

      Get Started

      -

      Go here to try out basic step-by-step samples.

      +
      +

      Super Simple Editing App

      +

      +
      +
      + + + +

      Basic Editing Only

      +

      This bare-bones sample provides lightweight protection from the occasional internet connection interruption while editing. + It automatically manages storing edits while the app is offline and then resync's the edits when the app returns online. +

      +
      + +
      +
      -
      -

      Examples

      +

      Advanced Apps

      Check out the following full-featured applications.

      @@ -175,14 +189,13 @@

      Supported Browsers

      Important note for Hybrid app developers (e.g. PhoneGap\Cordova): this library is not supported for hybrid deployments. - There are too many different variations of iOS and Android to make this feasible. + There are too many different variations of iOS and Android browser's and versions to make this feasible. We've only done very limited proof-of-concept testing using WebView. Make sure you do thorough testing on as many different phones and tablets as possible. One suggestion is to build a test app and run the Unit Test suite which is in this project under /test.

      - Windows developers: Edge is under consideration for developement support-only. However, at this time I don't have - a machine that runs it. + Windows developers: Edge is under consideration for developement support-only.

      * - means that IndexedDBShim.js may be required on this browser/platform. More info available in the README under Dependencies.

      diff --git a/demo/samples/editing-step1.html b/demo/samples/editing-step1.html deleted file mode 100644 index 56a8540b..00000000 --- a/demo/samples/editing-step1.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - Offline Features - - - - - - - - - - - - - - - -
      -
      -
      - - Pending Edits 0 -
      -
      - -
      -
      -
      -
      -
      -
      -
      -
      - - - - - - - - - - \ No newline at end of file diff --git a/demo/samples/editing-step2.html b/demo/samples/editing-step2.html deleted file mode 100644 index 79f12ec8..00000000 --- a/demo/samples/editing-step2.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - Offline Features - - - - - - - - - - - - - - - -
      -
      -
      - - Pending Edits 0 -
      -
      - -
      -
      -
      -
      -
      -
      -
      -
      - - - - - - - - - - \ No newline at end of file diff --git a/demo/samples/editing-step3.html b/demo/samples/editing-step3.html deleted file mode 100644 index 12258972..00000000 --- a/demo/samples/editing-step3.html +++ /dev/null @@ -1,363 +0,0 @@ - - - - - - Offline Features - - - - - - - - - - - - - - - -
      -
      -
      - - Pending Edits 0 -
      -
      - -
      -
      -
      -
      -
      -
      -
      -
      - - - - - - - - - - \ No newline at end of file diff --git a/demo/widgets/modal/css/modal-popup.css b/demo/widgets/modal/css/modal-popup.css deleted file mode 100644 index 0567e5dc..00000000 --- a/demo/widgets/modal/css/modal-popup.css +++ /dev/null @@ -1,198 +0,0 @@ -.mod-popup-div { - opacity: 0; - height: 0; - width: 0; - z-index: 98; - font-size: x-large; - position: absolute; - top: 0px; - left: -1000px; -} -.mod-popup-body { - position: relative; - top: 10%; - left: 10%; - z-index: 100; - height: 80%; - width: 80%; - border-radius: 10px; - background-color: black; - display: table; - opacity: 0.7; -} -.mod-popup-modal-background { - position: absolute; - top: 0; - left: 0; - height: 100%; - width: 100%; - opacity: 0.5; - background-color: black; - z-index: 99; - overflow: visible; -} -.mod-popup-input { - border-bottom: solid #ffffff 1px; - width: 80%; - display: table-cell; - vertical-align: middle; - padding-left: 12px; -} -.mod-popup-label { - padding: 12px; - width: 20%; - display: table-cell; - vertical-align: middle; - background-color: dimgrey; -} -.mod-popup-label-top-left { - padding: 12px; - width: 20%; - display: table-cell; - vertical-align: middle; - background-color: dimgray; - border-top-left-radius: 10px; -} -.mod-popup-table-row { - color: white; - border-radius: 10px; - display: table-row; -} -.mod-popup-stop-input { - border-radius: 5px; - font-size: x-large; - width: 90%; - height: 75%; - padding: 5px; -} -.mod-popup-stop-input-disabled { - color: white; - border-radius: 5px; - font-size: x-large; - background-color: dimgray; - opacity: 1.0; /* For safari display bug */ - padding: 5px; - width: 90%; - height: 75%; -} -.mod-popup-button { - position: relative; - float: left; - color: #ffffff; - font-size: x-large; - border-radius: 10px; - width: 45%; - padding: 8px; - background-color: #000000; - border: solid #ffffff 2px; -} -.mod-popup-button:active { - position: relative; - float: left; - color: #000000; - font-size: x-large; - border-radius: 10px; - width: 45%; - padding: 8px; - background-color: lightyellow; - border: solid #ffffff 2px; -} -.mod-popup-button-cancel { - position: relative; - float: left; - color: lightgray; - font-size: x-large; - border-radius: 10px; - width: 100%; - padding: 8px; - background-color: #000000; - border: solid lightgray 1px; -} -.mod-popup-button-cancel:active { - position: relative; - float: left; - color: #000000; - font-size: x-large; - border-radius: 10px; - width: 100%; - padding: 8px; - background-color: lightyellow; - border: solid lightgray 1px; -} -.mod-popup-button-div { - padding: 12px; - display: table-cell; - vertical-align: middle; - background-color: #000000; -} -.mod-popup-button-div-bottom-left { - padding: 12px; - display: table-cell; - vertical-align: middle; - background-color: #000000; - border-bottom-left-radius: 8px; -} -@media (max-width: 500px) { - .mod-popup-button { - font-size: small; - } - .mod-popup-button:active{ - font-size: small; - } - .mod-popup-button-cancel { - font-size: small; - } - .mod-popup-button-cancel:active { - font-size: small; - } - .mod-popup-stop-input { - font-size: small; - } - .mod-popup-stop-input-disabled { - font-size: small; - } -} -@media (max-width: 450px) { - .mod-popup-button { - font-size: x-small; - } - .mod-popup-button:active{ - font-size: x-small; - } - .mod-popup-button-cancel { - font-size: x-small; - } - .mod-popup-button-cancel:active { - font-size: x-small; - } - .mod-popup-stop-input { - font-size: small; - } - .mod-popup-stop-input-disabled { - font-size: small; - } -} -@media (max-height: 500px) { - - .mod-popup-button { - font-size: small; - } - .mod-popup-button:active{ - font-size: small; - } - .mod-popup-button-cancel { - font-size: small; - } - .mod-popup-button-cancel:active { - font-size: small; - } - .mod-popup-stop-input { - font-size: small; - } - .mod-popup-stop-input-disabled { - font-size: small; - } - .mod-popup-modal-background { - - } -} \ No newline at end of file diff --git a/demo/widgets/modal/popup.js b/demo/widgets/modal/popup.js deleted file mode 100644 index 00dfd3d4..00000000 --- a/demo/widgets/modal/popup.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Modal Popup Widget - * This widget provides a basic framework for building modal popups - * for mobile GIS web applications. - * @author @agup - */ -define([ - "dojo/_base/declare", "dojo/parser", "dojo/ready", - "dijit/_WidgetBase", "dijit/_TemplatedMixin","dojo/query", - "dojo/text!./template/popup.html","dojo/NodeList-manipulate" -], function(declare, parser, ready, _WidgetBase, _TemplatedMixin,query,template){ - - return declare("ModalPopup", [_WidgetBase, _TemplatedMixin], { - - options: { - animation: false, - animationDuration: 1 - }, - - templateString: template, - - constructor: function (options, srcRefNode) { - // mix in settings and defaults - declare.safeMixin(this.options, options); - - // widget node - this.domNode = srcRefNode; - - // Set properties - this.set("animation", this.options.animation); - this.set("animationDuration", this.options.animationDuration); - }, - - show: function () { - - if(this.animation){ - // You can design any animation you want! - this.domNode.style.opacity = 1; - this.domNode.style.left = 0; - this.domNode.style.top = 0; - this.domNode.style.width = "100%"; - this.domNode.style.height = "100%"; - this.domNode.style.transition = "all " + this.animationDuration + "s linear 0s"; - } - else{ - this.domNode.style.position = "static"; - } - }, - - hide: function () { - - if(this.animation){ - // You can design any animation you want! - this.domNode.style.height = 0; - this.domNode.style.width = 0; - this.domNode.style.opacity = 0; - this.domNode.style.top = "0px"; - this.domNode.style.left = -1000 + "px"; - this.domNode.style.transition = "all " + this.animationDuration + "s ease-in-out 0s"; - } - else{ - this.domNode.style.position = "absolute"; - } - }, - - // connections/subscriptions will be cleaned up during the destroy() lifecycle phase - destroy: function () { - this.inherited(arguments); - } - }); -}); diff --git a/demo/widgets/modal/template/popup.html b/demo/widgets/modal/template/popup.html deleted file mode 100644 index eeed14c9..00000000 --- a/demo/widgets/modal/template/popup.html +++ /dev/null @@ -1,46 +0,0 @@ -
      - -
      -
      -
      ID
      -
      - -
      -
      -
      -
      Bustop ID
      -
      - -
      -
      -
      -
      Routes
      -
      - -
      -
      -
      -
      Stopnames
      -
      - -
      -
      -
      -
      - -
      -
      - - -
      -
      -
      - -
      \ No newline at end of file diff --git a/dist/offline-edit-advanced-min.js b/dist/offline-edit-advanced-min.js new file mode 100644 index 00000000..a105dd15 --- /dev/null +++ b/dist/offline-edit-advanced-min.js @@ -0,0 +1,226 @@ +/*! esri-offline-maps - v3.0.0 - 2015-11-23 +* Copyright (c) 2015 Environmental Systems Research Institute, Inc. +* Apache License*/ +Offline.options={checks:{image:{url:function(){return"http://esri.github.io/offline-editor-js/tiny-image.png?_="+Math.floor(1e9*Math.random())}},active:"image"}},define(["dojo/Evented","dojo/_base/Deferred","dojo/promise/all","dojo/_base/declare","dojo/_base/array","dojo/dom-attr","dojo/dom-style","dojo/query","esri/config","esri/layers/GraphicsLayer","esri/graphic","esri/request","esri/symbols/SimpleMarkerSymbol","esri/symbols/SimpleLineSymbol","esri/symbols/SimpleFillSymbol","esri/urlUtils"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p){"use strict" +return d("O.esri.Edit.OfflineEditAdvanced",[a],{_onlineStatus:"online",_featureLayers:{},_featureCollectionUsageFlag:!1,_editStore:new O.esri.Edit.EditStore,_defaultXhrTimeout:15e3,ONLINE:"online",OFFLINE:"offline",RECONNECTING:"reconnecting",attachmentsStore:null,proxyPath:null,ENABLE_FEATURECOLLECTION:!1,DB_NAME:"features_store",DB_OBJECTSTORE_NAME:"features",DB_UID:"objectid",ATTACHMENTS_DB_NAME:"attachments_store",ATTACHMENTS_DB_OBJECTSTORE_NAME:"attachments",events:{EDITS_SENT:"edits-sent",EDITS_ENQUEUED:"edits-enqueued",EDITS_ENQUEUED_ERROR:"edits-enqueued-error",EDITS_SENT_ERROR:"edits-sent-error",ALL_EDITS_SENT:"all-edits-sent",ATTACHMENT_ENQUEUED:"attachment-enqueued",ATTACHMENTS_SENT:"attachments-sent"},initAttachments:function(a){if(a=a||function(a){},!this._checkFileAPIs())return a(!1,"File APIs not supported") +try{if(this.attachmentsStore=new O.esri.Edit.AttachmentsStore,this.attachmentsStore.dbName=this.ATTACHMENTS_DB_NAME,this.attachmentsStore.objectStoreName=this.ATTACHMENTS_DB_OBJECTSTORE_NAME,!this.attachmentsStore.isSupported())return a(!1,"indexedDB not supported") +this.attachmentsStore.init(a)}catch(b){}},extend:function(a,d,i){function l(){try{a._phantomLayer=new j({opacity:.8}),a._map.addLayer(a._phantomLayer)}catch(b){}}var m=[],n=this +a.offlineExtended=!0,!a.loaded,a.objectIdField=this.DB_UID +var o=null +a.url&&(o=a.url,this._featureLayers[a.url]=a),a._mode.featureLayer.hasOwnProperty("_collection")&&(this._featureCollectionUsageFlag=!0),this._editStore._isDBInit||m.push(this._initializeDB(i,o)),a._applyEdits=a.applyEdits,a._addAttachment=a.addAttachment,a._queryAttachmentInfos=a.queryAttachmentInfos,a._deleteAttachments=a.deleteAttachments,a._updateAttachment=a.updateAttachment,a.queryAttachmentInfos=function(a,c,d){if(n.getOnlineStatus()===n.ONLINE){var e=this._queryAttachmentInfos(a,function(){n.emit(n.events.ATTACHMENTS_INFO,arguments),c&&c.apply(this,arguments)},d) +return e}if(n.attachmentsStore){var f=new b +return n.attachmentsStore.getAttachmentsByFeatureId(this.url,a,function(a){c&&c(a),f.resolve(a)}),f}},a.addAttachment=function(a,c,d,e){if(n.getOnlineStatus()===n.ONLINE)return this._addAttachment(a,c,function(){n.emit(n.events.ATTACHMENTS_SENT,arguments),d&&d.apply(this,arguments)},function(a){e&&e.apply(this,arguments)}) +if(n.attachmentsStore){var f=this._getFilesFromForm(c),g=f[0],i=new b,j=this._getNextTempId() +return n.attachmentsStore.store(this.url,j,a,g,n.attachmentsStore.TYPE.ADD,function(b,c){var f={attachmentId:j,objectId:a,success:b} +if(b){n.emit(n.events.ATTACHMENT_ENQUEUED,f),d&&d(f),i.resolve(f) +var g=this._url.path+"/"+a+"/attachments/"+j,k=h("[href="+g+"]") +k.attr("href",c.url)}else f.error="can't store attachment",e&&e(f),i.reject(f)}.bind(this)),i}},a.updateAttachment=function(a,c,d,e,f){if(n.getOnlineStatus()===n.ONLINE)return this._updateAttachment(a,c,d,function(){e&&e.apply(this,arguments)},function(a){f&&f.apply(this,arguments)}) +if(n.attachmentsStore){var g=this._getFilesFromForm(d),i=g[0],j=n.attachmentsStore.TYPE.UPDATE,k=new b +return 0>c&&(j=n.attachmentsStore.TYPE.ADD),n.attachmentsStore.store(this.url,c,a,i,j,function(b,d){var g={attachmentId:c,objectId:a,success:b} +if(b){n.emit(n.events.ATTACHMENT_ENQUEUED,g),e&&e(g),k.resolve(g) +var i=this._url.path+"/"+a+"/attachments/"+c,j=h("[href="+i+"]") +j.attr("href",d.url)}else g.error="layer.updateAttachment::attachmentStore can't store attachment",f&&f(g),k.reject(g)}.bind(this)),k}},a.deleteAttachments=function(a,d,e,f){if(n.getOnlineStatus()===n.ONLINE){var g=this._deleteAttachments(a,d,function(){e&&e.apply(this,arguments)},function(a){f&&f.apply(this,arguments)}) +return g}if(n.attachmentsStore){var h=[] +d.forEach(function(c){c=parseInt(c,10) +var d=new b +if(0>c)n.attachmentsStore["delete"](c,function(b){var e={objectId:a,attachmentId:c,success:b} +d.resolve(e)}) +else{var e=new Blob([],{type:"image/png"}) +n.attachmentsStore.store(this.url,c,a,e,n.attachmentsStore.TYPE.DELETE,function(b,e){var f={attachmentId:c,objectId:a,success:b} +b?d.resolve(f):d.reject(f)}.bind(this))}h.push(d)},this) +var i=c(h) +return i.then(function(a){e&&e(a)}),i}},a.applyEdits=function(d,e,f,g,h){var i=[] +if(n.getOnlineStatus()===n.ONLINE){var j=this._applyEdits(d,e,f,function(){n.emit(n.events.EDITS_SENT,arguments),g&&g.apply(this,arguments)},h) +return j}var k=new b,l={addResults:[],updateResults:[],deleteResults:[]},m={},o=d||[] +return o.forEach(function(a){var c=new b,d=this._getNextTempId() +a.attributes[this.objectIdField]=d +var e=this +this._validateFeature(a,this.url,n._editStore.ADD).then(function(b){b.success?e._pushValidatedAddFeatureToDB(e,a,b.operation,l,d,c):c.resolve(!0)},function(a){c.reject(a)}),i.push(c)},this),e=e||[],e.forEach(function(a){var c=new b,d=a.attributes[this.objectIdField] +m[d]=a +var e=this +this._validateFeature(a,this.url,n._editStore.UPDATE).then(function(b){b.success?e._pushValidatedUpdateFeatureToDB(e,a,b.operation,l,d,c):c.resolve(!0)},function(a){c.reject(a)}),i.push(c)},this),f=f||[],f.forEach(function(a){var c=new b,d=a.attributes[this.objectIdField],e=this +this._validateFeature(a,this.url,n._editStore.DELETE).then(function(b){b.success?e._pushValidatedDeleteFeatureToDB(e,a,b.operation,l,d,c):c.resolve(!0)},function(a){c.reject(a)}),i.push(c)},this),c(i).then(function(b){for(var c=!0,d=0;dg;g++){var h=a[g].toJson() +if(f.push(h),g==e-1){var i=JSON.stringify(f),j=JSON.stringify(d) +c(i,j) +break}}},a.getFeatureLayerJSON=function(a,b){require(["esri/request"],function(c){var d=c({url:a,content:{f:"json"},handleAs:"json",callbackParamName:"callback"}) +d.then(function(a){b(!0,a)},function(a){b(!1,a.message)})})},a.setFeatureLayerJSONDataStore=function(a,b){n._editStore.pushFeatureLayerJSON(a,function(a,c){b(a,c)})},a.getFeatureLayerJSONDataStore=function(a){n._editStore.getFeatureLayerJSON(function(b,c){a(b,c)})},a.setPhantomLayerGraphics=function(a){var b=a.length +if(b>0)for(var c=0;b>c;c++){var d=new k(a[c]) +this._phantomLayer.add(d)}},a.getPhantomLayerGraphics=function(b){for(var c=a._phantomLayer.graphics,d=a._phantomLayer.graphics.length,e=[],f=0;d>f;f++){var g=c[f].toJson() +if(e.push(g),f==d-1){var h=JSON.stringify(e) +b(h) +break}}},a.getPhantomGraphicsArray=function(a){n._editStore.getPhantomGraphicsArray(function(b,c){"end"==c?a(!0,b):a(!1,c)})},a.getAttachmentsUsage=function(a){n.attachmentsStore.getUsage(function(b,c){a(b,c)})},a.resetAttachmentsDatabase=function(a){n.attachmentsStore.resetAttachmentsQueue(function(b,c){a(b,c)})},a.getUsage=function(a){n._editStore.getUsage(function(b,c){a(b,c)})},a.resetDatabase=function(a){n._editStore.resetEditsQueue(function(b,c){a(b,c)})},a.pendingEditsCount=function(a){n._editStore.pendingEditsCount(function(b){a(b)})},a.getFeatureDefinition=function(a,b,c,d){var e={layerDefinition:a,featureSet:{features:b,geometryType:c}} +d(e)},a.getAllEditsArray=function(a){n._editStore.getAllEditsArray(function(b,c){"end"==c?a(!0,b):a(!1,c)})},a._pushFeatureCollections=function(b){n._editStore._getFeatureCollections(function(c,d){var e={featureLayerUrl:a.url,featureLayerCollection:a.toJson()},f=[e],g={id:n._editStore.FEATURE_COLLECTION_ID,featureCollections:f} +if(a.hasAttachments=e.featureLayerCollection.layerDefinition.hasAttachments,c){for(var h=0,i=0;id;d++)n.attachmentsStore.replaceFeatureId(this.url,a[d],b[d],function(a){--f,g+=a?1:0,0===f&&c(g)}.bind(this))},a._nextTempId=-1,a._getNextTempId=function(){return this._nextTempId--},l(),c(m).then(function(b){0===b.length&&o?this.ENABLE_FEATURECOLLECTION?a._pushFeatureCollections(function(a){a?d(!0,null):d(!1,null)}):d(!0,null):b[0].success&&!o?this._editStore.getFeatureLayerJSON(function(b,c){b?(this._featureLayers[c.__featureLayerURL]=a,a.url=c.__featureLayerURL,this.ENABLE_FEATURECOLLECTION?a._pushFeatureCollections(function(a){a?d(!0,null):d(!1,null)}):d(!0,null)):d(!1,c)}.bind(this)):b[0].success&&(this.ENABLE_FEATURECOLLECTION?a._pushFeatureCollections(function(a){a?d(!0,null):d(!1,null)}):d(!0,null))}.bind(this))},goOffline:function(){this._onlineStatus=this.OFFLINE},goOnline:function(a){this._onlineStatus=this.RECONNECTING,this._replayStoredEdits(function(b,c){var d={success:b,responses:c} +this._onlineStatus=this.ONLINE,null!=this.attachmentsStore?this._sendStoredAttachments(function(b,c,e){d.attachments={success:b,responses:c,dbResponses:e},a&&a(d)}.bind(this)):a&&a(d)}.bind(this))},getOnlineStatus:function(){return this._onlineStatus},serializeFeatureGraphicsArray:function(a,b){for(var c=a.length,d=[],e=0;c>e;e++){var f=a[e].toJson() +if(d.push(f),e==c-1){var g=JSON.stringify(d) +b(g) +break}}},getFeatureCollections:function(a){this._editStore._isDBInit?this._editStore._getFeatureCollections(function(b,c){a(b,c)}):this._initializeDB(null,null).then(function(b){b.success&&this._editStore._getFeatureCollections(function(b,c){a(b,c)})}.bind(this),function(b){a(!1,b)})},getFeatureLayerJSONDataStore:function(a){this._editStore._isDBInit?this._editStore.getFeatureLayerJSON(function(b,c){a(b,c)}):this._initializeDB(null,null).then(function(b){b.success&&this._editStore.getFeatureLayerJSON(function(b,c){a(b,c)})}.bind(this),function(b){a(!1,b)})},_initializeDB:function(a,c){var d=new b,e=this._editStore +return e.dbName=this.DB_NAME,e.objectStoreName=this.DB_OBJECTSTORE_NAME,e.objectId=this.DB_UID,e.init(function(b,f){"object"==typeof a&&b===!0&&void 0!==a&&null!==a?(c&&(a.__featureLayerURL=c),e.pushFeatureLayerJSON(a,function(a,b){a?d.resolve({success:!0,error:null}):d.reject({success:!1,error:b})})):b?d.resolve({success:!0,error:null}):d.reject({success:!1,error:null})}),d},_checkFileAPIs:function(){return window.File&&window.FileReader&&window.FileList&&window.Blob?(XMLHttpRequest.prototype.sendAsBinary||(XMLHttpRequest.prototype.sendAsBinary=function(a){function b(a){return 255&a.charCodeAt(0)}var c=Array.prototype.map.call(a,b),d=new Uint8Array(c) +this.send(d.buffer)}),!0):!1},_extendAjaxReq:function(a){a.sendAsBinary=XMLHttpRequest.prototype.sendAsBinary},_phantomSymbols:[],_getPhantomSymbol:function(a,b){if(0===this._phantomSymbols.length){var c=[0,255,0,255],d=1.5 +this._phantomSymbols.point=[],this._phantomSymbols.point[this._editStore.ADD]=new m({type:"esriSMS",style:"esriSMSCross",xoffset:10,yoffset:10,color:[255,255,255,0],size:15,outline:{color:c,width:d,type:"esriSLS",style:"esriSLSSolid"}}),this._phantomSymbols.point[this._editStore.UPDATE]=new m({type:"esriSMS",style:"esriSMSCircle",xoffset:0,yoffset:0,color:[255,255,255,0],size:15,outline:{color:c,width:d,type:"esriSLS",style:"esriSLSSolid"}}),this._phantomSymbols.point[this._editStore.DELETE]=new m({type:"esriSMS",style:"esriSMSX",xoffset:0,yoffset:0,color:[255,255,255,0],size:15,outline:{color:c,width:d,type:"esriSLS",style:"esriSLSSolid"}}),this._phantomSymbols.multipoint=null,this._phantomSymbols.polyline=[],this._phantomSymbols.polyline[this._editStore.ADD]=new n({type:"esriSLS",style:"esriSLSSolid",color:c,width:d}),this._phantomSymbols.polyline[this._editStore.UPDATE]=new n({type:"esriSLS",style:"esriSLSSolid",color:c,width:d}),this._phantomSymbols.polyline[this._editStore.DELETE]=new n({type:"esriSLS",style:"esriSLSSolid",color:c,width:d}),this._phantomSymbols.polygon=[],this._phantomSymbols.polygon[this._editStore.ADD]=new o({type:"esriSFS",style:"esriSFSSolid",color:[255,255,255,0],outline:{type:"esriSLS",style:"esriSLSSolid",color:c,width:d}}),this._phantomSymbols.polygon[this._editStore.UPDATE]=new o({type:"esriSFS",style:"esriSFSSolid",color:[255,255,255,0],outline:{type:"esriSLS",style:"esriSLSDash",color:c,width:d}}),this._phantomSymbols.polygon[this._editStore.DELETE]=new o({type:"esriSFS",style:"esriSFSSolid",color:[255,255,255,0],outline:{type:"esriSLS",style:"esriSLSDot",color:c,width:d}})}return this._phantomSymbols[a.type][b]},_uploadAttachment:function(a){var c=new b,d=this._featureLayers[a.featureLayerUrl],e=new FormData +switch(e.append("attachment",a.file),a.type){case this.attachmentsStore.TYPE.ADD:d.addAttachment(a.objectId,e,function(b){c.resolve({attachmentResult:b,id:a.id})},function(a){c.reject(a)}) +break +case this.attachmentsStore.TYPE.UPDATE:e.append("attachmentId",a.id),d._sendAttachment("update",a.objectId,e,function(b){c.resolve({attachmentResult:b,id:a.id})},function(a){c.reject(a)}) +break +case this.attachmentsStore.TYPE.DELETE:d.deleteAttachments(a.objectId,[a.id],function(b){c.resolve({attachmentResult:b,id:a.id})},function(a){c.reject(a)})}return c.promise},_deleteAttachmentFromDB:function(a,c){var d=new b +return this.attachmentsStore["delete"](a,function(a){d.resolve({success:a,result:c})}),d},_cleanAttachmentsDB:function(a,b){var d=this,e=[],f=0 +a.forEach(function(a){"object"==typeof a.attachmentResult&&a.attachmentResult.success?e.push(d._deleteAttachmentFromDB(a.id,null)):a.attachmentResult instanceof Array?a.attachmentResult.forEach(function(b){b.success?e.push(d._deleteAttachmentFromDB(a.id,null)):f++}):f++}) +var g=c(e) +g.then(function(c){b(f>0?{errors:!0,attachmentsDBResults:c,uploadResults:a}:{errors:!1,attachmentsDBResults:c,uploadResults:a})})},_sendStoredAttachments:function(a){this.attachmentsStore.getAllAttachments(function(b){var d=this,e=[] +b.forEach(function(a){var b=this._uploadAttachment(a) +e.push(b)},this) +var f=c(e) +f.then(function(b){d._cleanAttachmentsDB(b,function(c){c.errors?a&&a(!1,b,c):a&&a(!0,b,c)})},function(b){a&&a(!1,b)})}.bind(this))},_replayStoredEdits:function(a){var b,d={},e=this,f=[],g=[],h=[],i=[],j=[],l=this._featureLayers,m=this.attachmentsStore,n=this._editStore +this._editStore.getAllEditsArray(function(o,p){if(o.length>0){j=o +for(var q=j.length,r=0;q>r;r++){b=l[j[r].layer],null==m&&b.hasAttachments,b._attachmentsStore=m,b.__onEditsComplete=b.onEditsComplete,b.onEditsComplete=function(){},f=[],g=[],h=[],i=[] +var s=new k(j[r].graphic) +switch(j[r].operation){case n.ADD:for(var t=0;t0){var j=b.map(function(a){return a.objectId}) +a._replaceFeatureIds(d,j,function(a){})}if(b.length>0){var l=new k(e[0].geometry,null,e[0].attributes) +a.add(l)}h._cleanDatabase(a,d,b,f,g).then(function(e){i.resolve({id:c,layer:a.url,tempId:d,addResults:b,updateResults:f,deleteResults:g,databaseResults:e,databaseErrors:null,syncError:null})},function(e){i.resolve({id:c,layer:a.url,tempId:d,addResults:b,updateResults:f,deleteResults:g,databaseResults:null,databaseErrors:e,syncError:e})})},function(b){a.onEditsComplete=a.__onEditsComplete,delete a.__onEditsComplete,i.reject(b)}),i.promise},_cleanDatabase:function(a,c,d,e,f){var g=new b,h=null +e.length>0&&e[0].success&&(h=e[0].objectId),f.length>0&&f[0].success&&(h=f[0].objectId),d.length>0&&d[0].success&&(h=c) +var i={} +return i.attributes={},i.attributes[this.DB_UID]=h,this._editStore["delete"](a.url,i,function(a,b){if(a){var c=this._editStore.PHANTOM_GRAPHIC_PREFIX+this._editStore._PHANTOM_PREFIX_TOKEN+i.attributes[this.DB_UID] +this._editStore.deletePhantomGraphic(c,function(a,b){a?g.resolve({success:!0,error:null,id:c}):g.reject({success:!1,error:b,id:c})})}else g.reject({success:!1,error:b,id:c})}.bind(this)),g.promise},_makeEditRequest:function(a,b,c,d,f,g){var h="f=json",i="",j="",k="" +if(b.length>0&&(e.forEach(b,function(a){a.hasOwnProperty("infoTemplate")&&delete a.infoTemplate},this),i="&adds="+JSON.stringify(b)),c.length>0&&(e.forEach(c,function(a){a.hasOwnProperty("infoTemplate")&&delete a.infoTemplate},this),j="&updates="+JSON.stringify(c)),d.length>0){var l=d[0].attributes[this.DB_UID] +k="&deletes="+l}var m=h+i+j+k +a.hasOwnProperty("credential")&&a.credential&&a.credential.hasOwnProperty("token")&&a.credential.token&&(m=m+"&token="+a.credential.token) +var n=new XMLHttpRequest +n.open("POST",a.url+"/applyEdits",!0),n.setRequestHeader("Content-type","application/x-www-form-urlencoded"),n.onload=function(){if(200===n.status&&""!==n.responseText)try{var a=JSON.parse(this.response) +f(a.addResults,a.updateResults,a.deleteResults)}catch(b){g("Unable to parse xhr response",n)}},n.onerror=function(a){g(a)},n.ontimeout=function(){g("xhr timeout error")},n.timeout=this._defaultXhrTimeout,n.send(m)},_parseResponsesArray:function(a){var c=new b,d=0 +for(var e in a)a.hasOwnProperty(e)&&(a[e].addResults.map(function(a){a.success||d++}),a[e].updateResults.map(function(a){a.success||d++}),a[e].deleteResults.map(function(a){a.success||d++})) +return d>0?c.resolve(!1):c.resolve(!0),c.promise}})}),"undefined"!=typeof O?O.esri.Edit={}:(O={},O.esri={Edit:{}}),O.esri.Edit.EditStore=function(){"use strict" +this._db=null,this._isDBInit=!1,this.dbName="features_store",this.objectStoreName="features",this.objectId="objectid",this.ADD="add",this.UPDATE="update",this.DELETE="delete",this.FEATURE_LAYER_JSON_ID="feature-layer-object-1001",this.FEATURE_COLLECTION_ID="feature-collection-object-1001",this.PHANTOM_GRAPHIC_PREFIX="phantom-layer",this._PHANTOM_PREFIX_TOKEN="|@|",this.isSupported=function(){return window.indexedDB?!0:!1},this.pushEdit=function(a,b,c,d){var e={id:b+"/"+c.attributes[this.objectId],operation:a,layer:b,type:c.geometry.type,graphic:c.toJson()} +if("undefined"==typeof c.attributes[this.objectId])d(!1,"editsStore.pushEdit() - failed to insert undefined objectId into database. Did you set offlineEdit.DB_UID? "+JSON.stringify(c.attributes)) +else{var f=this._db.transaction([this.objectStoreName],"readwrite") +f.oncomplete=function(a){d(!0)},f.onerror=function(a){d(!1,a.target.error.message)} +var g=f.objectStore(this.objectStoreName) +g.put(e)}},this.pushFeatureLayerJSON=function(a,b){"object"!=typeof a&&b(!1,"dataObject type is not an object.") +var c=this._db +a.id=this.FEATURE_LAYER_JSON_ID,this.getFeatureLayerJSON(function(d,e){var f +if(d&&"undefined"!=typeof e){f=c.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName) +for(var g in a)a.hasOwnProperty(g)&&(e[g]=a[g]) +var h=f.put(e) +h.onsuccess=function(){b(!0,null)},h.onerror=function(a){b(!1,a)}}else{var i=c.transaction([this.objectStoreName],"readwrite") +i.oncomplete=function(a){b(!0,null)},i.onerror=function(a){b(!1,a.target.error.message)},f=i.objectStore(this.objectStoreName) +try{f.put(a)}catch(j){b(!1,JSON.stringify(j))}}}.bind(this))},this.getFeatureLayerJSON=function(a){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName),c=b.get(this.FEATURE_LAYER_JSON_ID) +c.onsuccess=function(){var b=c.result +"undefined"!=typeof b?a(!0,b):a(!1,"nothing found")},c.onerror=function(b){a(!1,b)}},this.deleteFeatureLayerJSON=function(a){var b=this._db,c=null,d=this,e=this.FEATURE_LAYER_JSON_ID +require(["dojo/Deferred"],function(f){c=new f,c.then(function(b){d.editExists(e).then(function(b){a(!1,{message:"object was not deleted."})},function(b){a(!0,{message:"id does not exist"})})},function(b){a(!1,{message:"id does not exist"})}),d.editExists(e).then(function(a){var f=b.transaction([d.objectStoreName],"readwrite").objectStore(d.objectStoreName),g=f["delete"](e) +g.onsuccess=function(){c.resolve(!0)},g.onerror=function(a){c.reject({success:!1,error:a})}},function(a){c.reject({success:!1,message:a})}.bind(this))})},this.pushPhantomGraphic=function(a,b){var c=this._db,d=this.PHANTOM_GRAPHIC_PREFIX+this._PHANTOM_PREFIX_TOKEN+a.attributes[this.objectId],e={id:d,graphic:a.toJson()},f=c.transaction([this.objectStoreName],"readwrite") +f.oncomplete=function(a){b(!0,null)},f.onerror=function(a){b(!1,a.target.error.message)} +var g=f.objectStore(this.objectStoreName) +g.put(e)},this.getPhantomGraphicsArray=function(a){var b=[] +if(null!==this._db){var c=this.PHANTOM_GRAPHIC_PREFIX,d=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor() +d.onsuccess=function(d){var e=d.target.result +e&&e.value&&e.value.id?(-1!=e.value.id.indexOf(c)&&b.push(e.value),e["continue"]()):a(b,"end")}.bind(this),d.onerror=function(b){a(null,b)}}else a(null,"no db")},this._getPhantomGraphicsArraySimple=function(a){var b=[] +if(null!==this._db){var c=this.PHANTOM_GRAPHIC_PREFIX,d=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor() +d.onsuccess=function(d){var e=d.target.result +e&&e.value&&e.value.id?(-1!=e.value.id.indexOf(c)&&b.push(e.value.id),e["continue"]()):a(b,"end")}.bind(this),d.onerror=function(b){a(null,b)}}else a(null,"no db")},this.deletePhantomGraphic=function(a,b){var c=this._db,d=null,e=this +require(["dojo/Deferred"],function(f){d=new f,e.editExists(a).then(function(f){d.then(function(c){e.editExists(a).then(function(a){b(!1,"item was not deleted")},function(a){b(!0,"item successfully deleted")})},function(a){b(!1,a)}) +var g=c.transaction([e.objectStoreName],"readwrite").objectStore(e.objectStoreName),h=g["delete"](a) +h.onsuccess=function(){d.resolve(!0)},h.onerror=function(a){d.reject({success:!1,error:a})}},function(a){b(!1,"item doesn't exist in db")})})},this.resetPhantomGraphicsQueue=function(a){var b=this._db +this._getPhantomGraphicsArraySimple(function(c){if(c!=[]){var d=0,e=b.transaction([this.objectStoreName],"readwrite"),f=e.objectStore(this.objectStoreName) +f.onerror=function(){d++},e.oncomplete=function(){a(0===d?!0:!1)} +for(var g=c.length,h=0;g>h;h++)f["delete"](c[h])}else a(!0)}.bind(this))},this.getEdit=function(a,b){var c=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName) +if("undefined"==typeof a)return void b(!1,"id is undefined.") +var d=c.get(a) +d.onsuccess=function(){var c=d.result +c&&c.id==a?b(!0,c):b(!1,"Id not found")},d.onerror=function(a){b(!1,a)}},this.getAllEdits=function(a){if(null!==this._db){var b=this.FEATURE_LAYER_JSON_ID,c=this.FEATURE_COLLECTION_ID,d=this.PHANTOM_GRAPHIC_PREFIX,e=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor() +e.onsuccess=function(e){var f=e.target.result +f&&f.hasOwnProperty("value")&&f.value.hasOwnProperty("id")?(f.value.id!==b&&f.value.id!==c&&-1==f.value.id.indexOf(d)&&a(f.value,null),f["continue"]()):a(null,"end")}.bind(this),e.onerror=function(b){a(null,b)}}else a(null,"no db")},this.getAllEditsArray=function(a){var b=[] +if(null!==this._db){var c=this.FEATURE_LAYER_JSON_ID,d=this.FEATURE_COLLECTION_ID,e=this.PHANTOM_GRAPHIC_PREFIX,f=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor() +f.onsuccess=function(f){var g=f.target.result +g&&g.value&&g.value.id?(g.value.id!==c&&g.value.id!==d&&-1==g.value.id.indexOf(e)&&b.push(g.value),g["continue"]()):a(b,"end")}.bind(this),f.onerror=function(b){a(null,b)}}else a(null,"no db")},this.updateExistingEdit=function(a,b,c,d){var e=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName),f=e.get(c.attributes[this.objectId]) +f.onsuccess=function(){f.result +var g={id:b+"/"+c.attributes[this.objectId],operation:a,layer:b,graphic:c.toJson()},h=e.put(g) +h.onsuccess=function(){d(!0)},h.onerror=function(a){d(!1,a)}}.bind(this)},this["delete"]=function(a,b,c){var d=this._db,e=null,f=this,g=a+"/"+b.attributes[this.objectId] +require(["dojo/Deferred"],function(a){e=new a,f.editExists(g).then(function(a){e.then(function(a){f.editExists(g).then(function(a){c(!1)},function(a){c(!0)})},function(a){c(!1,a)}) +var b=d.transaction([f.objectStoreName],"readwrite").objectStore(f.objectStoreName),h=b["delete"](g) +h.onsuccess=function(){e.resolve(!0)},h.onerror=function(a){e.reject({success:!1,error:a})}},function(a){c(!1)})})},this.resetEditsQueue=function(a){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear() +b.onsuccess=function(b){setTimeout(function(){a(!0)},0)},b.onerror=function(b){a(!1,b)}},this.pendingEditsCount=function(a){var b=0,c=this.FEATURE_LAYER_JSON_ID,d=this.FEATURE_COLLECTION_ID,e=this.PHANTOM_GRAPHIC_PREFIX,f=this._db.transaction([this.objectStoreName],"readwrite"),g=f.objectStore(this.objectStoreName) +g.openCursor().onsuccess=function(f){var g=f.target.result +g&&g.value&&g.value.id&&-1==g.value.id.indexOf(e)?(g.value.id!==c&&g.value.id!==d&&b++,g["continue"]()):a(b)}},this.editExists=function(a){var b=this._db,c=null,d=this +return require(["dojo/Deferred"],function(e){c=new e +var f=b.transaction([d.objectStoreName],"readwrite").objectStore(d.objectStoreName),g=f.get(a) +g.onsuccess=function(){var b=g.result +b&&b.id==a?c.resolve({success:!0,error:null}):c.reject({success:!1,error:"objectId is not a match."})},g.onerror=function(a){c.reject({success:!1,error:a})}}),c},this.getUsage=function(a){var b=this.FEATURE_LAYER_JSON_ID,c=this.FEATURE_COLLECTION_ID,d=this.PHANTOM_GRAPHIC_PREFIX,e={sizeBytes:0,editCount:0},f=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor() +f.onsuccess=function(f){var g=f.target.result +if(g&&g.value&&g.value.id){var h=g.value,i=JSON.stringify(h) +e.sizeBytes+=i.length,-1==g.value.id.indexOf(d)&&g.value.id!==b&&g.value.id!==c&&(e.editCount+=1),g["continue"]()}else a(e,null)},f.onerror=function(b){a(null,b)}},this._pushFeatureCollections=function(a,b){var c=this._db.transaction([this.objectStoreName],"readwrite") +c.oncomplete=function(a){b(!0)},c.onerror=function(a){b(!1,a.target.error.message)} +var d=c.objectStore(this.objectStoreName) +d.put(a)},this._getFeatureCollections=function(a){var b=this._db.transaction([this.objectStoreName],"readonly").objectStore(this.objectStoreName),c=b.get(this.FEATURE_COLLECTION_ID) +c.onsuccess=function(){var b=c.result +"undefined"!=typeof b?a(!0,b):a(!1,null)},c.onerror=function(b){a(!1,b)}},this.init=function(a){var b=indexedDB.open(this.dbName,11) +a=a||function(a){}.bind(this),b.onerror=function(b){a(!1,b.target.errorCode)}.bind(this),b.onupgradeneeded=function(a){var b=a.target.result +b.objectStoreNames.contains(this.objectStoreName)&&b.deleteObjectStore(this.objectStoreName),b.createObjectStore(this.objectStoreName,{keyPath:"id"})}.bind(this),b.onsuccess=function(b){this._db=b.target.result,this._isDBInit=!0,a(!0,null)}.bind(this)}},O.esri.Edit.AttachmentsStore=function(){"use strict" +this._db=null,this.dbName="attachments_store",this.objectStoreName="attachments",this.TYPE={ADD:"add",UPDATE:"update",DELETE:"delete"},this.isSupported=function(){return window.indexedDB?!0:!1},this.store=function(a,b,c,d,e,f){try{e==this.TYPE.ADD||e==this.TYPE.UPDATE||e==this.TYPE.DELETE?this._readFile(d,function(g,h){if(g){var i={id:b,objectId:c,type:e,featureId:a+"/"+c,contentType:d.type,name:d.name,size:d.size,featureLayerUrl:a,content:h,file:d},j=this._db.transaction([this.objectStoreName],"readwrite") +j.oncomplete=function(a){f(!0,i)},j.onerror=function(a){f(!1,a.target.error.message)} +try{j.objectStore(this.objectStoreName).put(i)}catch(k){f(!1,k)}}else f(!1,h)}.bind(this)):f(!1,"attachmentsStore.store() Invalid type in the constructor!")}catch(g){f(!1,g.stack)}},this.retrieve=function(a,b){var c=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName),d=c.get(a) +d.onsuccess=function(a){var c=a.target.result +c?b(!0,c):b(!1,"not found")},d.onerror=function(a){b(!1,a)}},this.getAttachmentsByFeatureId=function(a,b,c){var d=a+"/"+b,e=[],f=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName),g=f.index("featureId"),h=IDBKeyRange.only(d) +g.openCursor(h).onsuccess=function(a){var b=a.target.result +b?(e.push(b.value),b["continue"]()):c(e)}},this.getAttachmentsByFeatureLayer=function(a,b){var c=[],d=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName),e=d.index("featureLayerUrl"),f=IDBKeyRange.only(a) +e.openCursor(f).onsuccess=function(a){var d=a.target.result +d?(c.push(d.value),d["continue"]()):b(c)}},this.getAllAttachments=function(a){var b=[],c=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName) +c.openCursor().onsuccess=function(c){var d=c.target.result +d?(b.push(d.value),d["continue"]()):a(b)}},this.deleteAttachmentsByFeatureId=function(a,b,c){var d=a+"/"+b,e=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName),f=e.index("featureId"),g=IDBKeyRange.only(d),h=0 +f.openCursor(g).onsuccess=function(a){var b=a.target.result +b?(e["delete"](b.primaryKey),h++,b["continue"]()):setTimeout(function(){c(h)},0)}.bind(this)},this["delete"]=function(a,b){this.retrieve(a,function(c,d){if(!c)return void b(!1,"attachment "+a+" not found") +var e=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName)["delete"](a) +e.onsuccess=function(a){setTimeout(function(){b(!0)},0)},e.onerror=function(a){b(!1,a)}}.bind(this))},this.deleteAll=function(a){this.getAllAttachments(function(b){var c=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear() +c.onsuccess=function(b){setTimeout(function(){a(!0)},0)},c.onerror=function(b){a(!1,b)}}.bind(this))},this.replaceFeatureId=function(a,b,c,d){var e=a+"/"+b,f=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName),g=f.index("featureId"),h=IDBKeyRange.only(e),i=0 +g.openCursor(h).onsuccess=function(b){var e=b.target.result +if(e){var g=a+"/"+c,h=e.value +h.featureId=g,h.objectId=c,f.put(h),i++,e["continue"]()}else setTimeout(function(){d(i)},1)}},this.getUsage=function(a){var b={sizeBytes:0,attachmentCount:0},c=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor() +c.onsuccess=function(c){var d=c.target.result +if(d){var e=d.value,f=JSON.stringify(e) +b.sizeBytes+=f.length,b.attachmentCount+=1,d["continue"]()}else a(b,null)}.bind(this),c.onerror=function(b){a(null,b)}},this.resetAttachmentsQueue=function(a){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear() +b.onsuccess=function(b){setTimeout(function(){a(!0)},0)},b.onerror=function(b){a(!1,b)}},this._readFile=function(a,b){var c=new FileReader +c.onload=function(a){b(!0,a.target.result)},c.onerror=function(a){b(!1,a.target.result)},c.readAsBinaryString(a)},this.init=function(a){var b=indexedDB.open(this.dbName,12) +a=a||function(a){}.bind(this),b.onerror=function(b){a(!1,b.target.errorCode)}.bind(this),b.onupgradeneeded=function(a){var b=a.target.result +b.objectStoreNames.contains(this.objectStoreName)&&b.deleteObjectStore(this.objectStoreName) +var c=b.createObjectStore(this.objectStoreName,{keyPath:"id"}) +c.createIndex("featureId","featureId",{unique:!1}),c.createIndex("featureLayerUrl","featureLayerUrl",{unique:!1})}.bind(this),b.onsuccess=function(b){this._db=b.target.result,a(!0)}.bind(this)}} diff --git a/dist/offline-edit-src.js b/dist/offline-edit-advanced-src.js similarity index 92% rename from dist/offline-edit-src.js rename to dist/offline-edit-advanced-src.js index 1b084d4f..841b4250 100644 --- a/dist/offline-edit-src.js +++ b/dist/offline-edit-advanced-src.js @@ -1,6 +1,19 @@ -/*! esri-offline-maps - v2.16.0 - 2015-10-29 +/*! esri-offline-maps - v3.0.0 - 2015-11-23 * Copyright (c) 2015 Environmental Systems Research Institute, Inc. * Apache License*/ +// Configure offline/online detection +// Requires: http://github.hubspot.com/offline/docs/welcome/ + +Offline.options = { // jshint ignore:line + checks: { + image: { + url: function() { + return 'http://esri.github.io/offline-editor-js/tiny-image.png?_=' + (Math.floor(Math.random() * 1000000000)); + } + }, + active: 'image' + } +}; /*jshint -W030 */ define([ "dojo/Evented", @@ -22,7 +35,7 @@ define([ function (Evented, Deferred, all, declare, array, domAttr, domStyle, query, esriConfig, GraphicsLayer, Graphic, esriRequest, SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol, urlUtils) { "use strict"; - return declare("O.esri.Edit.OfflineFeaturesManager", [Evented], + return declare("O.esri.Edit.OfflineEditAdvanced", [Evented], { _onlineStatus: "online", _featureLayers: {}, @@ -60,7 +73,6 @@ define([ ALL_EDITS_SENT: "all-edits-sent", // ...after going online and there are no pending edits in the queue ATTACHMENT_ENQUEUED: "attachment-enqueued", ATTACHMENTS_SENT: "attachments-sent", - EXTEND_COMPLETE: "extend-complete" // ...when the libary has completed its initialization }, /** @@ -114,8 +126,8 @@ define([ var self = this; layer.offlineExtended = true; // to identify layer has been extended - if(!layer.loaded || layer._url === null) { - console.error("Make sure to initialize OfflineFeaturesManager after layer loaded and feature layer update-end event."); + if(!layer.loaded) { + console.error("Make sure to initialize OfflineEditAdvanced after layer loaded and feature layer update-end event."); } // NOTE: At v2.6.1 we've discovered that not all feature layers support objectIdField. @@ -193,7 +205,7 @@ define([ } if (!self.attachmentsStore) { - console.log("in order to support attachments you need to call initAttachments() method of offlineFeaturesManager"); + console.log("in order to support attachments you need to call initAttachments() method of OfflineEditAdvanced"); return; } @@ -223,7 +235,7 @@ define([ } if (!self.attachmentsStore) { - console.error("in order to support attachments you need to call initAttachments() method of offlineFeaturesManager"); + console.error("in order to support attachments you need to call initAttachments() method of OfflineEditAdvanced"); return; } @@ -268,7 +280,7 @@ define([ } if (!self.attachmentsStore) { - console.error("in order to support attachments you need to call initAttachments() method of offlineFeaturesManager"); + console.error("in order to support attachments you need to call initAttachments() method of OfflineEditAdvanced"); return; } @@ -320,7 +332,7 @@ define([ } if (!self.attachmentsStore) { - console.error("in order to support attachments you need to call initAttachments() method of offlineFeaturesManager"); + console.error("in order to support attachments you need to call initAttachments() method of OfflineEditAdvanced"); return; } @@ -779,7 +791,7 @@ define([ * use with offline browser restarts. You can retrieve the collections and use them * to reconstitute a featureLayer and then redisplay all the associated features. * - * To retrieve use OfflineFeaturesManager.getFeatureCollections(). + * To retrieve use OfflineEditAdvanced.getFeatureCollections(). * @param callback (boolean) * @private */ @@ -838,7 +850,7 @@ define([ } // Automatically update the featureCollectionsObject in the database with every ADD, UPDATE - // and DELETE. It can be retrieved via OfflineFeaturesManager.getFeatureCollections(); + // and DELETE. It can be retrieved via OfflineEditAdvanced.getFeatureCollections(); self._editStore._pushFeatureCollections(result, function(success, error) { if(!success){ console.error("There was a problem creating the featureCollectionObject: " + error); @@ -1257,7 +1269,7 @@ define([ * @param callback callback( boolean, errors ) */ goOnline: function (callback) { - console.log("offlineFeaturesManager going online"); + console.log("OfflineEditAdvanced going online"); this._onlineStatus = this.RECONNECTING; this._replayStoredEdits(function (success, responses) { var result = {success: success, responses: responses}; @@ -1718,7 +1730,7 @@ define([ // If the layer has attachments then check to see if the attachmentsStore has been initialized if (attachmentsStore == null && layer.hasAttachments) { - console.log("NOTICE: you may need to run OfflineFeaturesManager.initAttachments(). Check the Attachments doc for more info. Layer id: " + layer.id + " accepts attachments"); + console.log("NOTICE: you may need to run OfflineEditAdvanced.initAttachments(). Check the Attachments doc for more info. Layer id: " + layer.id + " accepts attachments"); } // Assign the attachmentsStore to the layer as a private var so we can access it from @@ -1769,7 +1781,7 @@ define([ var allPromises = all(promises); allPromises.then( function (responses) { - console.log("OfflineFeaturesManager sync - all responses are back"); + console.log("OfflineEditAdvanced sync - all responses are back"); this._parseResponsesArray(responses).then(function(result) { if(result) { @@ -1782,7 +1794,7 @@ define([ }.bind(this)); }.bind(that), function (errors) { - console.log("OfflineFeaturesManager._replayStoredEdits - ERROR!!"); + console.log("OfflineEditAdvanced._replayStoredEdits - ERROR!!"); console.log(errors); callback && callback(false, errors); }.bind(that) @@ -1796,83 +1808,6 @@ define([ }); }, - /** - * DEPRECATED as of v2.11 - - * TO-DO remove in next release - * Only delete items from database that were verified as successfully updated on the server. - * @param responses Object - * @param callback callback(true, responses) or callback(false, responses) - * @private - */ - _cleanSuccessfulEditsDatabaseRecords: function (responses, callback) { - if (Object.keys(responses).length !== 0) { - - var editsArray = []; - var editsFailedArray = []; - - for (var key in responses) { - if (responses.hasOwnProperty(key)) { - - var edit = responses[key]; - var tempResult = {}; - - if (edit.updateResults.length > 0) { - if (edit.updateResults[0].success) { - tempResult.layer = edit.layer; - tempResult.id = edit.updateResults[0].objectId; - editsArray.push(tempResult); - } - else { - editsFailedArray.push(edit); - } - } - if (edit.deleteResults.length > 0) { - if (edit.deleteResults[0].success) { - tempResult.layer = edit.layer; - tempResult.id = edit.deleteResults[0].objectId; - editsArray.push(tempResult); - } - else { - editsFailedArray.push(edit); - } - } - if (edit.addResults.length > 0) { - if (edit.addResults[0].success) { - tempResult.layer = edit.layer; - tempResult.id = edit.tempId; - editsArray.push(tempResult); - } - else { - editsFailedArray.push(edit); - } - } - } - } - - var promises = {}; - var length = editsArray.length; - for (var i = 0; i < length; i++) { - promises[i] = this._updateDatabase(editsArray[i]); - } - //console.log("EDIT LIST " + JSON.stringify(editsArray)); - - // wait for all requests to finish - // - var allPromises = all(promises); - allPromises.then( - function (responses) { - editsFailedArray.length > 0 ? callback(false, responses) : callback(true, responses); - }, - function (errors) { - callback(false, errors); - } - ); - } - else { - callback(true, {}); - } - }, - /** * Deletes edits from database. * This does not handle phantom graphics! @@ -1926,73 +1861,6 @@ define([ }); }, - /** - * DEPRECATED at v2.11 - * Executes the _applyEdits() method when a feature layer is created using a REST endpoint - * @param layer - * @param id the unique id that identifies the Graphic in the database - * @param tempObjectIds - * @param adds - * @param updates - * @param deletes - * @returns {l.Deferred.promise} contains {id,layer,tempId,addResults,updateResults,deleteResults} - * @private - */ - _internalApplyEdits: function (layer, id, tempObjectIds, adds, updates, deletes) { - var that = this; - var dfd = new Deferred(); - - layer._applyEdits(adds, updates, deletes, - function (addResults, updateResults, deleteResults) { - layer._phantomLayer.clear(); - - // We use a different pattern if the attachmentsStore is valid and the layer has attachments - if (layer._attachmentsStore != null && layer.hasAttachments && tempObjectIds.length > 0) { - - var newObjectIds = addResults.map(function (r) { - return r.objectId; - }); - - layer._replaceFeatureIds(tempObjectIds, newObjectIds, function (count) { - console.log("Done replacing feature ids. Total count = " + count); - }); - } - - that._cleanDatabase(layer, tempObjectIds, addResults, updateResults, deleteResults).then(function(results){ - dfd.resolve({ - id: id, - layer: layer.url, - tempId: tempObjectIds, // let's us internally match an ADD to it's new ObjectId - addResults: addResults, - updateResults: updateResults, - deleteResults: deleteResults, - databaseResults: results, - databaseErrors: null - }); // wrap three arguments in a single object - }, function(error) { - dfd.resolve({ - id: id, - layer: layer.url, - tempId: tempObjectIds, // let's us internally match an ADD to it's new ObjectId - addResults: addResults, - updateResults: updateResults, - deleteResults: deleteResults, - databaseResults: null, - databaseErrors: error - }); // wrap three arguments in a single object - }); - - }, - function (error) { - layer.onEditsComplete = layer.__onEditsComplete; - delete layer.__onEditsComplete; - - dfd.reject(error); - } - ); - return dfd.promise; - }, - /** * Applies edits. This works with both standard feature layers and when a feature layer is created * using a feature collection. @@ -2250,7 +2118,6 @@ define([ } }); // declare }); // define - /** * Creates a namespace for the non-AMD libraries in this directory */ @@ -2317,8 +2184,8 @@ O.esri.Edit.EditStore = function () { }; if(typeof graphic.attributes[this.objectId] === "undefined") { - console.error("editsStore.pushEdit() - failed to insert undefined objectId into database. Did you set offlineFeaturesManager.DB_UID? " + JSON.stringify(graphic.attributes)); - callback(false,"editsStore.pushEdit() - failed to insert undefined objectId into database. Did you set offlineFeaturesManager.DB_UID? " + JSON.stringify(graphic.attributes)); + console.error("editsStore.pushEdit() - failed to insert undefined objectId into database. Did you set offlineEdit.DB_UID? " + JSON.stringify(graphic.attributes)); + callback(false,"editsStore.pushEdit() - failed to insert undefined objectId into database. Did you set offlineEdit.DB_UID? " + JSON.stringify(graphic.attributes)); } else{ var transaction = this._db.transaction([this.objectStoreName], "readwrite"); @@ -2696,76 +2563,6 @@ O.esri.Edit.EditStore = function () { }); }; - /** - * DEPRECATED at v2.11 - * TO-DO remove in the next release - * - * Removes some phantom graphics from database. - * The responseObject contains {id,layer,tempId,addResults,updateResults,deleteResults}. - * IF there are no results.success then nothing will be deleted. - * - * WARNING: Can generate false positives. IndexedDB will always return success - * even if you attempt to delete a non-existent id. - * - * CAUTION: This should always be used in conjunction with deleting the phantom graphic's - * associated edit entry in the database. - * - * @param responseObject - * @param callback boolean - */ - this.resetLimitedPhantomGraphicsQueue = function (responseObject, callback) { - - if (Object.keys(responseObject).length > 0) { - var db = this._db; - - var errors = 0; - var tx = db.transaction([this.objectStoreName], "readwrite"); - var objectStore = tx.objectStore(this.objectStoreName); - - objectStore.onerror = function () { - errors++; - console.log("PHANTOM GRAPHIC ERROR"); - }; - - tx.oncomplete = function () { - errors === 0 ? callback(true) : callback(false); - }; - - for (var key in responseObject) { - if (responseObject.hasOwnProperty(key)) { - var edit = responseObject[key]; - var id = this.PHANTOM_GRAPHIC_PREFIX + this._PHANTOM_PREFIX_TOKEN + edit.id; - - // CAUTION: - // TO-DO we do NOT match the edit.id with edit's objectId - - // If we have an add, update or delete success then delete the entry, otherwise we skip it. - if(edit.updateResults.length > 0){ - if (edit.updateResults[0].success){ - objectStore.delete(id); - } - } - - if(edit.deleteResults.length > 0){ - if (edit.deleteResults[0].success){ - objectStore.delete(id); - } - } - - if(edit.addResults.length > 0){ - if (edit.addResults[0].success){ - objectStore.delete(id); - } - } - } - } - } - else { - callback(true); - } - }; - - /** * Removes all phantom graphics from database * @param callback boolean @@ -3211,36 +3008,6 @@ O.esri.Edit.EditStore = function () { }; }; - /** - * Save space in the database...don't need to store the entire Graphic object just its public properties! - * @param graphic - * @returns {*} - * @private - */ - this._serialize = function (graphic) { - // see http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Apply_Edits_Feature_Service_Layer/02r3000000r6000000/ - // use graphic's built-in serializing method - var json = graphic.toJson(); - var jsonClean = - { - attributes: json.attributes, - geometry: json.geometry, - infoTemplate: json.infoTemplate, - symbol: json.symbol - }; - return JSON.stringify(jsonClean); - }; - - this._deserialize = function (json) { - var graphic; - - require(["esri/graphic"], function (Graphic) { - graphic = new Graphic(JSON.parse(json)); - }); - - return graphic; - }; - this.init = function (callback) { console.log("init editsStore.js"); diff --git a/dist/offline-edit-basic-min.js b/dist/offline-edit-basic-min.js new file mode 100644 index 00000000..70f0eef5 --- /dev/null +++ b/dist/offline-edit-basic-min.js @@ -0,0 +1,97 @@ +/*! esri-offline-maps - v3.0.0 - 2015-11-23 +* Copyright (c) 2015 Environmental Systems Research Institute, Inc. +* Apache License*/ +Offline.options={checks:{image:{url:function(){return"http://esri.github.io/offline-editor-js/tiny-image.png?_="+Math.floor(1e9*Math.random())}},active:"image"}},define(["dojo/Evented","dojo/_base/Deferred","dojo/promise/all","dojo/_base/declare","dojo/_base/array","dojo/dom-attr","dojo/dom-style","dojo/query","dojo/on","esri/config","esri/layers/GraphicsLayer","esri/layers/FeatureLayer","esri/graphic"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){"use strict" +return d("O.esri.Edit.OfflineEditBasic",[a],{_onlineStatus:"online",_featureLayers:{},_editStore:new O.esri.Edit.EditStorePOLS,_defaultXhrTimeout:15e3,_autoOfflineDetect:!0,ONLINE:"online",OFFLINE:"offline",RECONNECTING:"reconnecting",proxyPath:null,DB_NAME:"features_store",DB_OBJECTSTORE_NAME:"features",DB_UID:"objectid",events:{EDITS_SENT:"edits-sent",EDITS_ENQUEUED:"edits-enqueued",EDITS_ENQUEUED_ERROR:"edits-enqueued-error"},constructor:function(a){a&&a.hasOwnProperty("autoDetect")&&(this._autoOfflineDetect=a.autoDetect)},extend:function(a,d){var f=[],g=this +a.offlineExtended=!0,!a.loaded||null===a._url,a.objectIdField=this.DB_UID +var h=null +a.url&&(h=a.url,this._featureLayers[a.url]=a),this._editStore._isDBInit||f.push(this._initializeDB(h)),a._applyEdits=a.applyEdits,a.applyEdits=function(d,e,f,h,i){var j=[] +if(g.getOnlineStatus()===g.ONLINE){var k=a._applyEdits(d,e,f,function(){g.emit(g.events.EDITS_SENT,arguments),h&&h.apply(this,arguments)},i) +return k}var l=new b,m={addResults:[],updateResults:[],deleteResults:[]},n={},o=d||[] +return o.forEach(function(a){var c=new b,d=this._getNextTempId() +a.attributes[this.objectIdField]=d +var e=this +this._validateFeature(a,this.url,g._editStore.ADD).then(function(b){b.success?e._pushValidatedAddFeatureToDB(e,a,b.operation,m,d,c):c.resolve(!0)},function(a){c.reject(a)}),j.push(c)},this),e=e||[],e.forEach(function(a){var c=new b,d=a.attributes[this.objectIdField] +n[d]=a +var e=this +this._validateFeature(a,this.url,g._editStore.UPDATE).then(function(b){b.success?e._pushValidatedUpdateFeatureToDB(e,a,b.operation,m,d,c):c.resolve(!0)},function(a){c.reject(a)}),j.push(c)},this),f=f||[],f.forEach(function(a){var c=new b,d=a.attributes[this.objectIdField],e=this +this._validateFeature(a,this.url,g._editStore.DELETE).then(function(b){b.success?e._pushValidatedDeleteFeatureToDB(e,a,b.operation,m,d,c):c.resolve(!0)},function(a){c.reject(a)}),j.push(c)},this),c(j).then(function(a){for(var b=!0,c=0;c0){j=n +for(var p=j.length,q=0;p>q;q++){b=k[j[q].layer],b.__onEditsComplete=b.onEditsComplete,b.onEditsComplete=function(){},f=[],g=[],h=[],i=[] +var r=new m(j[q].graphic) +switch(j[q].operation){case l.ADD:for(var s=0;s0&&(g.updateResults[0].success?(h.layer=g.layer,h.id=g.updateResults[0].objectId,d.push(h)):e.push(g)),g.deleteResults.length>0&&(g.deleteResults[0].success?(h.layer=g.layer,h.id=g.deleteResults[0].objectId,d.push(h)):e.push(g)),g.addResults.length>0&&(g.addResults[0].success?(h.layer=g.layer,h.id=g.tempId,d.push(h)):e.push(g))}for(var i={},j=d.length,k=0;j>k;k++)i[k]=this._updateDatabase(d[k]) +var l=c(i) +l.then(function(a){e.length>0?b(!1,a):b(!0,a)},function(a){b(!1,a)})}else b(!0,{})},_updateDatabase:function(a){var c=new b,d={} +return d.attributes={},d.attributes[this.DB_UID]=a.id,this._editStore["delete"](a.layer,d,function(a,b){a?c.resolve({success:!0,error:null}):c.reject({success:!1,error:b})}.bind(this)),c.promise},_internalApplyEditsAll:function(a,c,d,e,f,g){var h=this,i=new b +return this._makeEditRequest(a,e,f,g,function(b,f,g){if(b.length>0){var j=new m(e[0].geometry,null,e[0].attributes) +a.add(j)}h._cleanDatabase(a,d,b,f,g).then(function(e){i.resolve({id:c,layer:a.url,tempId:d,addResults:b,updateResults:f,deleteResults:g,databaseResults:e,databaseErrors:null,syncError:null})},function(e){i.resolve({id:c,layer:a.url,tempId:d,addResults:b,updateResults:f,deleteResults:g,databaseResults:null,databaseErrors:e,syncError:e})})},function(b){a.onEditsComplete=a.__onEditsComplete,delete a.__onEditsComplete,i.reject(b)}),i.promise},_cleanDatabase:function(a,c,d,e,f){var g=new b,h=null +e.length>0&&e[0].success&&(h=e[0].objectId),f.length>0&&f[0].success&&(h=f[0].objectId),d.length>0&&d[0].success&&(h=c) +var i={} +return i.attributes={},i.attributes[this.DB_UID]=h,this._editStore["delete"](a.url,i,function(a,b){a?g.resolve({success:!0,error:null,id:h}):g.reject({success:!1,error:b,id:h})}),g.promise},_makeEditRequest:function(a,b,c,d,f,g){var h="f=json",i="",j="",k="" +if(b.length>0&&(e.forEach(b,function(a){a.hasOwnProperty("infoTemplate")&&delete a.infoTemplate},this),i="&adds="+JSON.stringify(b)),c.length>0&&(e.forEach(c,function(a){a.hasOwnProperty("infoTemplate")&&delete a.infoTemplate},this),j="&updates="+JSON.stringify(c)),d.length>0){var l=d[0].attributes[this.DB_UID] +k="&deletes="+l}var m=h+i+j+k +a.hasOwnProperty("credential")&&a.credential&&a.credential.hasOwnProperty("token")&&a.credential.token&&(m=m+"&token="+a.credential.token) +var n=new XMLHttpRequest +n.open("POST",a.url+"/applyEdits",!0),n.setRequestHeader("Content-type","application/x-www-form-urlencoded"),n.onload=function(){if(200===n.status&&""!==n.responseText)try{var a=JSON.parse(this.response) +f(a.addResults,a.updateResults,a.deleteResults)}catch(b){g("Unable to parse xhr response",n)}},n.onerror=function(a){g(a)},n.ontimeout=function(){g("xhr timeout error")},n.timeout=this._defaultXhrTimeout,n.send(m)},_parseResponsesArray:function(a,b){var c=0 +for(var d in a)a.hasOwnProperty(d)&&(a[d].addResults.forEach(function(a){a.success||c++}),a[d].updateResults.forEach(function(a){a.success||c++}),a[d].deleteResults.forEach(function(a){a.success||c++})) +b(c>0?!1:!0)}})}),"undefined"!=typeof O?O.esri.Edit={}:(O={},O.esri={Edit:{}}),O.esri.Edit.EditStorePOLS=function(){"use strict" +this._db=null,this._isDBInit=!1,this.dbName="features_store",this.objectStoreName="features",this.objectId="objectid",this.ADD="add",this.UPDATE="update",this.DELETE="delete",this.FEATURE_LAYER_JSON_ID="feature-layer-object-1001",this.FEATURE_COLLECTION_ID="feature-collection-object-1001",this.isSupported=function(){return window.indexedDB?!0:!1},this.pushEdit=function(a,b,c,d){var e={id:b+"/"+c.attributes[this.objectId],operation:a,layer:b,type:c.geometry.type,graphic:c.toJson()} +if("undefined"==typeof c.attributes[this.objectId])d(!1,"editsStore.pushEdit() - failed to insert undefined objectId into database. Did you set offlineEdit.DB_UID? "+JSON.stringify(c.attributes)) +else{var f=this._db.transaction([this.objectStoreName],"readwrite") +f.oncomplete=function(a){d(!0)},f.onerror=function(a){d(!1,a.target.error.message)} +var g=f.objectStore(this.objectStoreName) +g.put(e)}},this.getEdit=function(a,b){var c=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName) +if("undefined"==typeof a)return void b(!1,"id is undefined.") +var d=c.get(a) +d.onsuccess=function(){var c=d.result +c&&c.id==a?b(!0,c):b(!1,"Id not found")},d.onerror=function(a){b(!1,a)}},this.getAllEditsArray=function(a){var b=[] +if(null!==this._db){var c=this.FEATURE_LAYER_JSON_ID,d=this.FEATURE_COLLECTION_ID,e=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor() +e.onsuccess=function(e){var f=e.target.result +f&&f.value&&f.value.id?(f.value.id!==c&&f.value.id!==d&&b.push(f.value),f["continue"]()):a(b,"end")}.bind(this),e.onerror=function(b){a(null,b)}}else a(null,"no db")},this.updateExistingEdit=function(a,b,c,d){var e=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName),f=e.get(c.attributes[this.objectId]) +f.onsuccess=function(){f.result +var g={id:b+"/"+c.attributes[this.objectId],operation:a,layer:b,graphic:c.toJson()},h=e.put(g) +h.onsuccess=function(){d(!0)},h.onerror=function(a){d(!1,a)}}.bind(this)},this["delete"]=function(a,b,c){var d=this._db,e=null,f=this,g=a+"/"+b.attributes[this.objectId] +require(["dojo/Deferred"],function(a){e=new a,f.editExists(g).then(function(a){e.then(function(a){f.editExists(g).then(function(a){c(!1)},function(a){c(!0)})},function(a){c(!1,a)}) +var b=d.transaction([f.objectStoreName],"readwrite").objectStore(f.objectStoreName),h=b["delete"](g) +h.onsuccess=function(){e.resolve(!0)},h.onerror=function(a){e.reject({success:!1,error:a})}},function(a){c(!1,a)})})},this.resetEditsQueue=function(a){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear() +b.onsuccess=function(b){setTimeout(function(){a(!0)},0)},b.onerror=function(b){a(!1,b)}},this.pendingEditsCount=function(a){var b=0,c=this.FEATURE_LAYER_JSON_ID,d=this.FEATURE_COLLECTION_ID,e=this._db.transaction([this.objectStoreName],"readwrite"),f=e.objectStore(this.objectStoreName) +f.openCursor().onsuccess=function(e){var f=e.target.result +f&&f.value&&f.value.id?(f.value.id!==c&&f.value.id!==d&&b++,f["continue"]()):a(b)}},this.editExists=function(a){var b=this._db,c=null,d=this +return require(["dojo/Deferred"],function(e){c=new e +var f=b.transaction([d.objectStoreName],"readwrite").objectStore(d.objectStoreName),g=f.get(a) +g.onsuccess=function(){var b=g.result +b&&b.id==a?c.resolve({success:!0,error:null}):c.reject({success:!1,error:"objectId is not a match."})},g.onerror=function(a){c.reject({success:!1,error:a})}}),c},this.getUsage=function(a){var b=this.FEATURE_LAYER_JSON_ID,c=this.FEATURE_COLLECTION_ID,d={sizeBytes:0,editCount:0},e=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor() +e.onsuccess=function(e){var f=e.target.result +if(f&&f.value&&f.value.id){var g=f.value,h=JSON.stringify(g) +d.sizeBytes+=h.length,f.value.id!==b&&f.value.id!==c&&(d.editCount+=1),f["continue"]()}else a(d,null)},e.onerror=function(b){a(null,b)}},this.init=function(a){var b=indexedDB.open(this.dbName,11) +a=a||function(a){}.bind(this),b.onerror=function(b){a(!1,b.target.errorCode)}.bind(this),b.onupgradeneeded=function(a){var b=a.target.result +b.objectStoreNames.contains(this.objectStoreName)&&b.deleteObjectStore(this.objectStoreName),b.createObjectStore(this.objectStoreName,{keyPath:"id"})}.bind(this),b.onsuccess=function(b){this._db=b.target.result,this._isDBInit=!0,a(!0,null)}.bind(this)}} diff --git a/dist/offline-edit-basic-src.js b/dist/offline-edit-basic-src.js new file mode 100644 index 00000000..c125af10 --- /dev/null +++ b/dist/offline-edit-basic-src.js @@ -0,0 +1,1457 @@ +/*! esri-offline-maps - v3.0.0 - 2015-11-23 +* Copyright (c) 2015 Environmental Systems Research Institute, Inc. +* Apache License*/ +// Configure offline/online detection +// Requires: http://github.hubspot.com/offline/docs/welcome/ + +Offline.options = { // jshint ignore:line + checks: { + image: { + url: function() { + return 'http://esri.github.io/offline-editor-js/tiny-image.png?_=' + (Math.floor(Math.random() * 1000000000)); + } + }, + active: 'image' + } +}; +/*jshint -W030 */ +/** + * This library is optimized for Partial Offline Support ONLY + */ +define([ + "dojo/Evented", + "dojo/_base/Deferred", + "dojo/promise/all", + "dojo/_base/declare", + "dojo/_base/array", + "dojo/dom-attr", + "dojo/dom-style", + "dojo/query", + "dojo/on", + "esri/config", + "esri/layers/GraphicsLayer", + "esri/layers/FeatureLayer", + "esri/graphic"], + function (Evented, Deferred, all, declare, array, domAttr, domStyle, query, on, + esriConfig, GraphicsLayer, FeatureLayer, Graphic) { + "use strict"; + return declare("O.esri.Edit.OfflineEditBasic", [Evented], + { + _onlineStatus: "online", + _featureLayers: {}, + _editStore: new O.esri.Edit.EditStorePOLS(), + _defaultXhrTimeout: 15000, // ms + _autoOfflineDetect: true, + + ONLINE: "online", // all edits will directly go to the server + OFFLINE: "offline", // edits will be enqueued + RECONNECTING: "reconnecting", // sending stored edits to the server + proxyPath: null, // by default we use CORS and therefore proxyPath is null + + // Database properties + DB_NAME: "features_store", // Sets the database name. + DB_OBJECTSTORE_NAME: "features",// Represents an object store that allows access to a set of data in the IndexedDB database + DB_UID: "objectid", // Set this based on the unique identifier is set up in the feature service + + // manager emits event when... + events: { + EDITS_SENT: "edits-sent", // ...whenever any edit is actually sent to the server + EDITS_ENQUEUED: "edits-enqueued", // ...when an edit is enqueued (and not sent to the server) + EDITS_ENQUEUED_ERROR: "edits-enqueued-error", // ...when there is an error during the queing process + }, + + constructor: function(options){ + if(options && options.hasOwnProperty("autoDetect")){ + this._autoOfflineDetect = options.autoDetect; + } + }, + + /** + * Overrides a feature layer. Call this AFTER the FeatureLayer's 'update-end' event. + * objects such as [esri.Graphic] will need to be serialized or you will get an IndexedDB error. + * @param layer + * @param updateEndEvent The FeatureLayer's update-end event object + * @param callback {true, null} or {false, errorString} Traps whether or not the database initialized + * @returns deferred + */ + extend: function (layer, callback) { + + var extendPromises = []; // deferred promises related to initializing this method + + var self = this; + layer.offlineExtended = true; // to identify layer has been extended + + if(!layer.loaded || layer._url === null) { + console.error("Make sure to initialize OfflineEditBasic after layer loaded and feature layer update-end event."); + } + + // NOTE: At v2.6.1 we've discovered that not all feature layers support objectIdField. + // However, to try to be consistent here with how the library is managing Ids + // we force the layer.objectIdField to DB_UID. This should be consistent with + // how esri.Graphics assign a unique ID to a graphic. If it is not, then this + // library will break and we'll have to re-architect how it manages UIDs. + layer.objectIdField = this.DB_UID; + + var url = null; + + // There have been reproducible use cases showing when a browser is restarted offline that + // for some reason the layer.url may be undefined. + // This is an attempt to minimize the possibility of that situation causing errors. + if(layer.url) { + url = layer.url; + // we keep track of the FeatureLayer object + this._featureLayers[layer.url] = layer; + } + + // Initialize the database as well as set offline data. + if(!this._editStore._isDBInit) { + extendPromises.push(this._initializeDB(url)); + } + + // replace the applyEdits() method + layer._applyEdits = layer.applyEdits; + + /** + * Overrides the ArcGIS API for JavaSccript applyEdits() method. + * @param adds Creates a new edit entry. + * @param updates Updates an existing entry. + * @param deletes Deletes an existing entry. + * @param callback Called when the operation is complete. + * @param errback An error object is returned if an error occurs + * @returns {*} deferred + * @event EDITS_ENQUEUED boolean if all edits successfully stored while offline + * @event EDITS_ENQUEUED_ERROR string message if there was an error while storing an edit while offline + */ + layer.applyEdits = function (adds, updates, deletes, callback, errback) { + // inside this method, 'this' will be the FeatureLayer + // and 'self' will be the offlineFeatureLayer object + var promises = []; + + if (self.getOnlineStatus() === self.ONLINE) { + var def = layer._applyEdits(adds, updates, deletes, + function () { + self.emit(self.events.EDITS_SENT, arguments); + callback && callback.apply(this, arguments); + }, + errback); + return def; + } + + var deferred1 = new Deferred(); + var results = {addResults: [], updateResults: [], deleteResults: []}; + var updatesMap = {}; + + var _adds = adds || []; + _adds.forEach(function (addEdit) { + var deferred = new Deferred(); + + var objectId = this._getNextTempId(); + + addEdit.attributes[this.objectIdField] = objectId; + + var thisLayer = this; + + // We need to run some validation tests against each feature being added. + // Adding the same feature multiple times results in the last edit wins. LIFO. + this._validateFeature(addEdit,this.url,self._editStore.ADD).then(function(result){ + console.log("EDIT ADD IS BACK!!! " ); + + if(result.success){ + thisLayer._pushValidatedAddFeatureToDB(thisLayer,addEdit,result.operation,results,objectId,deferred); + } + else{ + // If we get here then we deleted an edit that was added offline. + deferred.resolve(true); + } + + },function(error){ + console.log("_validateFeature: Unable to validate!"); + deferred.reject(error); + }); + + promises.push(deferred); + }, this); + + updates = updates || []; + updates.forEach(function (updateEdit) { + var deferred = new Deferred(); + + var objectId = updateEdit.attributes[this.objectIdField]; + updatesMap[objectId] = updateEdit; + + var thisLayer = this; + + // We need to run some validation tests against each feature being updated. + // If we have added a feature and we need to update it then we change it's operation type to "add" + // and the last edits wins. LIFO. + this._validateFeature(updateEdit,this.url,self._editStore.UPDATE).then(function(result){ + console.log("EDIT UPDATE IS BACK!!! " ); + + if(result.success){ + thisLayer._pushValidatedUpdateFeatureToDB(thisLayer,updateEdit,result.operation,results,objectId,deferred); + } + else{ + // If we get here then we deleted an edit that was added offline. + deferred.resolve(true); + } + + },function(error){ + console.log("_validateFeature: Unable to validate!"); + deferred.reject(error); + }); + + promises.push(deferred); + }, this); + + deletes = deletes || []; + deletes.forEach(function (deleteEdit) { + var deferred = new Deferred(); + + var objectId = deleteEdit.attributes[this.objectIdField]; + + var thisLayer = this; + + // We need to run some validation tests against each feature being deleted. + // If we have added a feature and then deleted it in the app + this._validateFeature(deleteEdit,this.url,self._editStore.DELETE).then(function(result){ + console.log("EDIT DELETE IS BACK!!! " ); + + if(result.success){ + thisLayer._pushValidatedDeleteFeatureToDB(thisLayer,deleteEdit,result.operation,results,objectId,deferred); + } + else{ + // If we get here then we deleted an edit that was added offline. + deferred.resolve(true); + } + + },function(error){ + console.log("_validateFeature: Unable to validate!"); + deferred.reject(error); + }); + + promises.push(deferred); + }, this); + + all(promises).then(function (r) { + // Make sure all edits were successful. If not throw an error. + var promisesSuccess = true; + for (var v = 0; v < r.length; v++) { + if (r[v] === false) { + promisesSuccess = false; + } + } + + promisesSuccess === true ? self.emit(self.events.EDITS_ENQUEUED, results) : self.emit(self.events.EDITS_ENQUEUED_ERROR, results); + this._editHandler(results, _adds, updatesMap, callback, errback, deferred1); + }.bind(this)); + + return deferred1; + + }; // layer.applyEdits() + + /** + * Returns the approximate size of the edits database in bytes + * @param callback callback({usage}, error) Whereas, the usage Object is {sizeBytes: number, editCount: number} + */ + layer.getUsage = function(callback){ + self._editStore.getUsage(function(usage,error){ + callback(usage,error); + }); + }; + + /** + * Full edits database reset. + * CAUTION! If some edits weren't successfully sent, then their record + * will still exist in the database. If you use this function you + * will also delete those records. + * @param callback (boolean, error) + */ + layer.resetDatabase = function(callback){ + self._editStore.resetEditsQueue(function(result,error){ + callback(result,error); + }); + }; + + /** + * Returns the number of edits pending in the database. + * @param callback callback( int ) + */ + layer.pendingEditsCount = function(callback){ + self._editStore.pendingEditsCount(function(count){ + callback(count); + }); + }; + + /** + * Create a featureDefinition + * @param featureLayer + * @param featuresArr + * @param geometryType + * @param callback + */ + layer.getFeatureDefinition = function (/* Object */ featureLayer, /* Array */ featuresArr, /* String */ geometryType, callback) { + + var featureDefinition = { + "layerDefinition": featureLayer, + "featureSet": { + "features": featuresArr, + "geometryType": geometryType + } + + }; + + callback(featureDefinition); + }; + + /** + * Returns an iterable array of all edits stored in the database + * Each item in the array is an object and contains: + * { + * id: "internal ID", + * operation: "add, update or delete", + * layer: "layerURL", + * type: "esri Geometry Type", + * graphic: "esri.Graphic converted to JSON then serialized" + * } + * @param callback (true, array) or (false, errorString) + */ + layer.getAllEditsArray = function(callback){ + self._editStore.getAllEditsArray(function(array,message){ + if(message == "end"){ + callback(true,array); + } + else{ + callback(false,message); + } + }); + }; + + /* internal methods */ + + /** + * Pushes a DELETE request to the database after it's been validated + * @param layer + * @param deleteEdit + * @param operation + * @param resultsArray + * @param objectId + * @param deferred + * @private + */ + layer._pushValidatedDeleteFeatureToDB = function(layer,deleteEdit,operation,resultsArray,objectId,deferred){ + self._editStore.pushEdit(operation, layer.url, deleteEdit, function (result, error) { + + if(result){ + resultsArray.deleteResults.push({success: true, error: null, objectId: objectId}); + + // Use the correct key as set by self.DB_UID + var tempIdObject = {}; + tempIdObject[self.DB_UID] = objectId; + } + else{ + resultsArray.deleteResults.push({success: false, error: error, objectId: objectId}); + } + + deferred.resolve(result); + }); + }; + + /** + * Pushes an UPDATE request to the database after it's been validated + * @param layer + * @param updateEdit + * @param operation + * @param resultsArray + * @param objectId + * @param deferred + * @private + */ + layer._pushValidatedUpdateFeatureToDB = function(layer,updateEdit,operation,resultsArray,objectId,deferred){ + self._editStore.pushEdit(operation, layer.url, updateEdit, function (result, error) { + + if(result){ + resultsArray.updateResults.push({success: true, error: null, objectId: objectId}); + + // Use the correct key as set by self.DB_UID + var tempIdObject = {}; + tempIdObject[self.DB_UID] = objectId; + } + else{ + resultsArray.updateResults.push({success: false, error: error, objectId: objectId}); + } + + deferred.resolve(result); + }); + }; + + /** + * Pushes an ADD request to the database after it's been validated + * @param layer + * @param addEdit + * @param operation + * @param resultsArray + * @param objectId + * @param deferred + * @private + */ + layer._pushValidatedAddFeatureToDB = function(layer,addEdit,operation,resultsArray,objectId,deferred){ + self._editStore.pushEdit(operation, layer.url, addEdit, function (result, error) { + if(result){ + resultsArray.addResults.push({success: true, error: null, objectId: objectId}); + + // Use the correct key as set by self.DB_UID + var tempIdObject = {}; + tempIdObject[self.DB_UID] = objectId; + } + else{ + resultsArray.addResults.push({success: false, error: error, objectId: objectId}); + } + + deferred.resolve(result); + }); + }; + + /** + * Validates duplicate entries. Last edit on same feature can overwite any previous values. + * Note: if an edit was already added offline and you delete it then we return success == false + * @param graphic esri.Graphic. + * @param layerUrl the URL of the feature service + * @param operation add, update or delete action on an edit + * @returns deferred {success:boolean,graphic:graphic,operation:add|update|delete} + * @private + */ + layer._validateFeature = function (graphic,layerUrl,operation) { + + var deferred = new Deferred(); + + var id = layerUrl + "/" + graphic.attributes[self.DB_UID]; + + self._editStore.getEdit(id,function(success,result){ + if (success) { + switch( operation ) + { + case self._editStore.ADD: + // Not good - however we'll allow the new ADD to replace/overwrite existing edit + // and pass it through unmodified. Last ADD wins. + deferred.resolve({"success":true,"graphic":graphic,"operation":operation}); + break; + case self._editStore.UPDATE: + // If we are doing an update on a feature that has not been added to + // the server yet, then we need to maintain its operation as an ADD + // and not an UPDATE. This avoids the potential for an error if we submit + // an update operation on a feature that has not been added to the + // database yet. + if(result.operation == self._editStore.ADD){ + graphic.operation = self._editStore.ADD; + operation = self._editStore.ADD; + } + deferred.resolve({"success":true,"graphic":graphic,"operation":operation}); + break; + case self._editStore.DELETE: + + var resolved = true; + + if(result.operation == self._editStore.ADD){ + // If we are deleting a new feature that has not been added to the + // server yet we need to delete it + layer._deleteTemporaryFeature(graphic,function(success, error){ + if(!success){ + resolved = false; + console.log("Unable to delete feature: " + JSON.stringify(error)); + } + }); + } + deferred.resolve({"success":resolved,"graphic":graphic,"operation":operation}); + break; + } + } + else if(result == "Id not found"){ + // Let's simply pass the graphic back as good-to-go. + // No modifications needed because the graphic does not + // already exist in the database. + deferred.resolve({"success":true,"graphic":graphic,"operation":operation}); + } + else{ + deferred.reject(graphic); + } + }); + + return deferred; + }; + + /** + * Delete a graphic that has been added while offline. + * @param graphic + * @param callback + * @private + */ + layer._deleteTemporaryFeature = function(graphic,callback){ + self._editStore.delete(layer.url,graphic,function(success,error){ + callback(success, error); + }); + }; + + layer._getFilesFromForm = function (formNode) { + var files = []; + var inputNodes = array.filter(formNode.elements, function (node) { + return node.type === "file"; + }); + inputNodes.forEach(function (inputNode) { + files.push.apply(files, inputNode.files); + }, this); + return files; + }; + + // we need to identify ADDs before sending them to the server + // we assign temporary ids (using negative numbers to distinguish them from real ids) + layer._nextTempId = -1; + layer._getNextTempId = function () { + return this._nextTempId--; + }; + + // We are currently only passing in a single deferred. + all(extendPromises).then(function (r) { + + if(self._autoOfflineDetect){ + Offline.on('up', function(){ // jshint ignore:line + + self.goOnline(function(success,error){ // jshint ignore:line + console.log("GOING ONLINE"); + }); + }); + + Offline.on('down', function(){ // jshint ignore:line + self.goOffline(); // jshint ignore:line + }); + } + + callback(true, null); + }); + + }, // extend + + /** + * Forces library into an offline state. Any edits applied during this condition will be stored locally + */ + goOffline: function () { + console.log("offlineFeatureManager going offline"); + this._onlineStatus = this.OFFLINE; + }, + + /** + * Forces library to return to an online state. If there are pending edits, + * an attempt will be made to sync them with the remote feature server + * @param callback callback( boolean, errors ) + */ + goOnline: function (callback) { + console.log("OfflineEditBasic going online"); + this._onlineStatus = this.RECONNECTING; + this._replayStoredEdits(function (success, responses) { + //var result = {success: success, responses: responses}; + this._onlineStatus = this.ONLINE; + + //this._onlineStatus = this.ONLINE; + callback && callback(success,responses); + + }.bind(this)); + }, + + /** + * Determines if offline or online condition exists + * @returns {string} ONLINE or OFFLINE + */ + getOnlineStatus: function () { + return this._onlineStatus; + }, + + /* internal methods */ + + /** + * Initialize the database and push featureLayer JSON to DB if required. + * @param url Feature Layer's url. This is used by this library for internal feature identification. + * @return deferred + * @private + */ + _initializeDB: function(url){ + var deferred = new Deferred(); + + var editStore = this._editStore; + + // Configure the database + editStore.dbName = this.DB_NAME; + editStore.objectStoreName = this.DB_OBJECTSTORE_NAME; + editStore.objectId = this.DB_UID; + + // Attempt to initialize the database + editStore.init(function (result, error) { + + if(result){ + deferred.resolve({success:true, error: null}); + } + else{ + deferred.reject({success:false, error: null}); + } + }); + + return deferred; + }, + + // + // methods to send features back to the server + // + + /** + * Attempts to send any edits in the database. Monitor events for success or failure. + * @param callback + * @event ALL_EDITS_SENT when all edits have been successfully sent. Contains {[addResults],[updateResults],[deleteResults]} + * @event EDITS_SENT_ERROR some edits were not sent successfully. Contains {msg: error} + * @private + */ + _replayStoredEdits: function (callback) { + var promises = {}; + var that = this; + + // + // send edits for each of the layers + // + var layer; + var adds = [], updates = [], deletes = []; + var tempObjectIds = []; + var tempArray = []; + var featureLayers = this._featureLayers; + + var editStore = this._editStore; + + this._editStore.getAllEditsArray(function (result, err) { + if (result.length > 0) { + tempArray = result; + + var length = tempArray.length; + + for (var n = 0; n < length; n++) { + layer = featureLayers[tempArray[n].layer]; + layer.__onEditsComplete = layer.onEditsComplete; + layer.onEditsComplete = function () { + console.log("intercepting events onEditsComplete"); + }; + + // Let's zero everything out + adds = [], updates = [], deletes = [], tempObjectIds = []; + + // IMPORTANT: reconstitute the graphic JSON into an actual esri.Graphic object + // NOTE: we are only sending one Graphic per loop! + var graphic = new Graphic(tempArray[n].graphic); + + switch (tempArray[n].operation) { + case editStore.ADD: + for (var i = 0; i < layer.graphics.length; i++) { + var g = layer.graphics[i]; + if (g.attributes[layer.objectIdField] === graphic.attributes[layer.objectIdField]) { + layer.remove(g); + break; + } + } + tempObjectIds.push(graphic.attributes[layer.objectIdField]); + delete graphic.attributes[layer.objectIdField]; + adds.push(graphic); + break; + case editStore.UPDATE: + updates.push(graphic); + break; + case editStore.DELETE: + deletes.push(graphic); + break; + } + + // Note: when the feature layer is created with a feature collection we have to handle applyEdits() differently + // TO-DO rename this method. + promises[n] = that._internalApplyEditsAll(layer, tempArray[n].id, tempObjectIds, adds, updates, deletes); + } + + // wait for all requests to finish + // responses contain {id,layer,tempId,addResults,updateResults,deleteResults} + var allPromises = all(promises); + allPromises.then( + function (responses) { + console.log("OfflineEditBasic sync - all responses are back"); + callback(true, responses); + }, + function (errors) { + console.log("OfflineEditBasic._replayStoredEdits - ERROR!!"); + callback(false, errors); + } + ); + + } + else{ + // No edits were found + callback(true,[]); + } + }); + }, + + /** + * DEPRECATED as of v2.11 - + * TO-DO remove in next release + * Only delete items from database that were verified as successfully updated on the server. + * @param responses Object + * @param callback callback(true, responses) or callback(false, responses) + * @private + */ + _cleanSuccessfulEditsDatabaseRecords: function (responses, callback) { + if (Object.keys(responses).length !== 0) { + + var editsArray = []; + var editsFailedArray = []; + + for (var key in responses) { + if (responses.hasOwnProperty(key)) { + + var edit = responses[key]; + var tempResult = {}; + + if (edit.updateResults.length > 0) { + if (edit.updateResults[0].success) { + tempResult.layer = edit.layer; + tempResult.id = edit.updateResults[0].objectId; + editsArray.push(tempResult); + } + else { + editsFailedArray.push(edit); + } + } + if (edit.deleteResults.length > 0) { + if (edit.deleteResults[0].success) { + tempResult.layer = edit.layer; + tempResult.id = edit.deleteResults[0].objectId; + editsArray.push(tempResult); + } + else { + editsFailedArray.push(edit); + } + } + if (edit.addResults.length > 0) { + if (edit.addResults[0].success) { + tempResult.layer = edit.layer; + tempResult.id = edit.tempId; + editsArray.push(tempResult); + } + else { + editsFailedArray.push(edit); + } + } + } + } + + var promises = {}; + var length = editsArray.length; + for (var i = 0; i < length; i++) { + promises[i] = this._updateDatabase(editsArray[i]); + } + //console.log("EDIT LIST " + JSON.stringify(editsArray)); + + // wait for all requests to finish + // + var allPromises = all(promises); + allPromises.then( + function (responses) { + editsFailedArray.length > 0 ? callback(false, responses) : callback(true, responses); + }, + function (errors) { + callback(false, errors); + } + ); + } + else { + callback(true, {}); + } + }, + + /** + * Deletes edits from database. + * @param edit + * @returns {l.Deferred.promise|*|c.promise|q.promise|promise} + * @private + */ + _updateDatabase: function (edit) { + var dfd = new Deferred(); + var fakeGraphic = {}; + fakeGraphic.attributes = {}; + + // Use the correct attributes key! + fakeGraphic.attributes[this.DB_UID] = edit.id; + + this._editStore.delete(edit.layer, fakeGraphic, function (success, error) { + if (success) { + dfd.resolve({success: true, error: null}); + } + else { + dfd.reject({success: false, error: error}); + } + }.bind(this)); + + return dfd.promise; + + }, + + /** + * Applies edits. This works with both standard feature layers and when a feature layer is created + * using a feature collection. + * + * This works around specific behaviors in esri.layers.FeatureLayer when using the pattern + * new FeatureLayer(featureCollectionObject). + * + * Details on the specific behaviors can be found here: + * https://developers.arcgis.com/javascript/jsapi/featurelayer-amd.html#featurelayer2 + * + * @param layer + * @param id + * @param tempObjectIds + * @param adds + * @param updates + * @param deletes + * @returns {*|r} + * @private + */ + _internalApplyEditsAll: function (layer, id, tempObjectIds, adds, updates, deletes) { + var that = this; + var dfd = new Deferred(); + + this._makeEditRequest(layer, adds, updates, deletes, + function (addResults, updateResults, deleteResults) { + + if(addResults.length > 0) { + var graphic = new Graphic(adds[0].geometry,null,adds[0].attributes); + layer.add(graphic); + } + + that._cleanDatabase(layer, tempObjectIds, addResults, updateResults, deleteResults).then(function(results){ + dfd.resolve({ + id: id, + layer: layer.url, + tempId: tempObjectIds, // let's us internally match an ADD to it's new ObjectId + addResults: addResults, + updateResults: updateResults, + deleteResults: deleteResults, + databaseResults: results, + databaseErrors: null, + syncError: null + }); + }, function(error) { + dfd.resolve({ + id: id, + layer: layer.url, + tempId: tempObjectIds, // let's us internally match an ADD to it's new ObjectId + addResults: addResults, + updateResults: updateResults, + deleteResults: deleteResults, + databaseResults: null, + databaseErrors: error, + syncError: error + }); + }); + + }, + function (error) { + layer.onEditsComplete = layer.__onEditsComplete; + delete layer.__onEditsComplete; + + dfd.reject(error); + } + ); + return dfd.promise; + }, + + _cleanDatabase: function(layer, tempId, addResults, updateResults, deleteResults) { + + var dfd = new Deferred(); + var id = null; + + if (updateResults.length > 0) { + if (updateResults[0].success) { + id = updateResults[0].objectId; + } + } + if (deleteResults.length > 0) { + if (deleteResults[0].success) { + id = deleteResults[0].objectId; + } + } + if (addResults.length > 0) { + if (addResults[0].success) { + id = tempId; + } + } + + var fakeGraphic = {}; + fakeGraphic.attributes = {}; + + // Use the correct attributes key! + fakeGraphic.attributes[this.DB_UID] = id; + + // Delete the edit from the database + this._editStore.delete(layer.url, fakeGraphic, function (success, error) { + if (success) { + dfd.resolve({success: true, error: null, id: id}); + } + else { + dfd.reject({success: false, error: error, id: id}); + } + }); + + return dfd.promise; + }, + + /** + * Used when a feature layer is created with a feature collection. + * + * In the current version of the ArcGIS JSAPI 3.12+ the applyEdit() method doesn't send requests + * to the server when a feature layer is created with a feature collection. + * + * The use case for using this is: clean start app > go offline and make edits > offline restart browser > + * go online. + * + * @param layer + * @param adds + * @param updates + * @param deletes + * @returns {*|r} + * @private + */ + _makeEditRequest: function(layer,adds, updates, deletes, callback, errback) { + + var f = "f=json", a = "", u = "", d = ""; + + if(adds.length > 0) { + array.forEach(adds, function(add){ + if(add.hasOwnProperty("infoTemplate")){ // if the add has an infoTemplate attached, + delete add.infoTemplate; // delete it to reduce payload size. + } + }, this); + a = "&adds=" + JSON.stringify((adds)); + } + if(updates.length > 0) { + array.forEach(updates, function(update){ + if(update.hasOwnProperty("infoTemplate")){ // if the update has an infoTemplate attached, + delete update.infoTemplate; // delete it to reduce payload size. + } + }, this); + u = "&updates=" + JSON.stringify(updates); + } + if(deletes.length > 0) { + var id = deletes[0].attributes[this.DB_UID]; + d = "&deletes=" + id; + } + + var params = f + a + u + d; + + if(layer.hasOwnProperty("credential") && layer.credential){ + if(layer.credential.hasOwnProperty("token") && layer.credential.token){ + params = params + "&token=" + layer.credential.token; + } + } + + var req = new XMLHttpRequest(); + req.open("POST", layer.url + "/applyEdits", true); + req.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + req.onload = function() + { + if( req.status === 200 && req.responseText !== "") + { + try { + var obj = JSON.parse(this.response); + callback(obj.addResults, obj.updateResults, obj.deleteResults); + } + catch(err) { + console.error("EDIT REQUEST REPONSE WAS NOT SUCCESSFUL:", req); + errback("Unable to parse xhr response", req); + } + } + + }; + req.onerror = function(e) + { + console.error("_makeEditRequest failed: " + e); + errback(e); + }; + req.ontimeout = function() { + errback("xhr timeout error"); + }; + req.timeout = this._defaultXhrTimeout; + req.send(params); + }, + + /** + * Parses the respones related to going back online and cleaning up the database. + * @param responses + * @returns {promise} True means all was successful. False indicates there was a problem. + * @private + */ + _parseResponsesArray: function(responses,callback) { + + var err = 0; + + for (var key in responses) { + if (responses.hasOwnProperty(key)) { + responses[key].addResults.forEach(function(result){ + if(!result.success) { + err++; + } + }); + + responses[key].updateResults.forEach(function(result){ + if(!result.success) { + err++; + } + }); + + responses[key].deleteResults.forEach(function(result){ + if(!result.success) { + err++; + } + }); + } + } + + if(err > 0){ + callback(false); + } + else { + callback(true); + } + } + }); // declare + }); // define +/** + * Creates a namespace for the non-AMD libraries in this directory + */ +/*jshint -W020 */ +if(typeof O != "undefined"){ + O.esri.Edit = {}; +} +else{ + O = {}; + O.esri = { + Edit: {} + }; +} +/*global indexedDB */ +/*jshint -W030 */ +/** + * This library is optimized for Partial Offline Support ONLY + * @constructor + */ +O.esri.Edit.EditStorePOLS = function () { + + "use strict"; + + this._db = null; + this._isDBInit = false; + + // Public properties + + this.dbName = "features_store"; + this.objectStoreName = "features"; + this.objectId = "objectid"; // set this depending on how your feature service is configured; + + //var _dbIndex = "featureId"; // @private + + // ENUMs + + this.ADD = "add"; + this.UPDATE = "update"; + this.DELETE = "delete"; + + this.FEATURE_LAYER_JSON_ID = "feature-layer-object-1001"; + this.FEATURE_COLLECTION_ID = "feature-collection-object-1001"; + + this.isSupported = function () { + if (!window.indexedDB) { + return false; + } + return true; + }; + + /** + * Commit an edit to the database + * @param operation add, update or delete + * @param layerUrl the URL of the feature layer + * @param graphic esri/graphic. The method will serialize to JSON + * @param callback callback(true, edit) or callback(false, error) + */ + this.pushEdit = function (operation, layerUrl, graphic, callback) { + + var edit = { + id: layerUrl + "/" + graphic.attributes[this.objectId], + operation: operation, + layer: layerUrl, + type: graphic.geometry.type, + graphic: graphic.toJson() + }; + + if(typeof graphic.attributes[this.objectId] === "undefined") { + console.error("editsStore.pushEdit() - failed to insert undefined objectId into database. Did you set offlineEdit.DB_UID? " + JSON.stringify(graphic.attributes)); + callback(false,"editsStore.pushEdit() - failed to insert undefined objectId into database. Did you set offlineEdit.DB_UID? " + JSON.stringify(graphic.attributes)); + } + else{ + var transaction = this._db.transaction([this.objectStoreName], "readwrite"); + + transaction.oncomplete = function (event) { + callback(true); + }; + + transaction.onerror = function (event) { + callback(false, event.target.error.message); + }; + + var objectStore = transaction.objectStore(this.objectStoreName); + objectStore.put(edit); + } + }; + + /** + * Retrieve an edit by its internal ID + * @param id String identifier + * @param callback callback(true,graphic) or callback(false, error) + */ + this.getEdit = function(id,callback){ + + console.assert(this._db !== null, "indexeddb not initialized"); + var objectStore = this._db.transaction([this.objectStoreName], "readwrite").objectStore(this.objectStoreName); + + if(typeof id === "undefined"){ + callback(false,"id is undefined."); + return; + } + + //Get the entry associated with the graphic + var objectStoreGraphicRequest = objectStore.get(id); + + objectStoreGraphicRequest.onsuccess = function () { + var graphic = objectStoreGraphicRequest.result; + if (graphic && (graphic.id == id)) { + callback(true,graphic); + } + else { + callback(false,"Id not found"); + } + }; + + objectStoreGraphicRequest.onerror = function (msg) { + callback(false,msg); + }; + }; + + /** + * Returns all the edits as a single Array via the callback + * @param callback {array, messageString} or {null, messageString} + */ + this.getAllEditsArray = function (callback) { + + console.assert(this._db !== null, "indexeddb not initialized"); + var editsArray = []; + + if (this._db !== null) { + + var fLayerJSONId = this.FEATURE_LAYER_JSON_ID; + var fCollectionId = this.FEATURE_COLLECTION_ID; + + var transaction = this._db.transaction([this.objectStoreName]) + .objectStore(this.objectStoreName) + .openCursor(); + + transaction.onsuccess = function (event) { + var cursor = event.target.result; + if (cursor && cursor.value && cursor.value.id) { + + // Make sure we are not return FeatureLayer JSON data + if (cursor.value.id !== fLayerJSONId && cursor.value.id !== fCollectionId) { + editsArray.push(cursor.value); + + } + cursor.continue(); + } + else { + callback(editsArray, "end"); + } + }.bind(this); + transaction.onerror = function (err) { + callback(null, err); + }; + } + else { + callback(null, "no db"); + } + }; + + /** + * Update an edit already exists in the database + * @param operation add, update or delete + * @param layer the URL of the feature layer + * @param graphic esri/graphic. The method will serialize to JSON + * @param callback {true, edit} or {false, error} + */ + this.updateExistingEdit = function (operation, layer, graphic, callback) { + + console.assert(this._db !== null, "indexeddb not initialized"); + + var objectStore = this._db.transaction([this.objectStoreName], "readwrite").objectStore(this.objectStoreName); + + //Let's get the entry associated with the graphic + var objectStoreGraphicRequest = objectStore.get(graphic.attributes[this.objectId]); + objectStoreGraphicRequest.onsuccess = function () { + + //Grab the data object returned as a result + // TO-DO Do we keep this?? + objectStoreGraphicRequest.result; + + //Create a new update object + var update = { + id: layer + "/" + graphic.attributes[this.objectId], + operation: operation, + layer: layer, + graphic: graphic.toJson() + }; + + // Insert the update into the database + var updateGraphicRequest = objectStore.put(update); + + updateGraphicRequest.onsuccess = function () { + callback(true); + }; + + updateGraphicRequest.onerror = function (err) { + callback(false, err); + }; + }.bind(this); + }; + + /** + * Delete a pending edit's record from the database. + * IMPORTANT: Be aware of false negatives. See Step 4 in this function. + * + * @param layerUrl + * @param graphic Graphic + * @param callback {boolean, error} + */ + this.delete = function (layerUrl, graphic, callback) { + + // NOTE: the implementation of the IndexedDB spec has a design fault with respect to + // handling deletes. The result of a delete operation is always designated as undefined. + // What this means is that there is no way to tell if an operation was successful or not. + // And, it will always return 'true.' + // + // In order to get around this we have to verify if after the attempted deletion operation + // if the record is or is not in the database. Kinda dumb, but that's how IndexedDB works. + //http://stackoverflow.com/questions/17137879/is-there-a-way-to-get-information-on-deleted-record-when-calling-indexeddbs-obj + + var db = this._db; + var deferred = null; + var self = this; + + var id = layerUrl + "/" + graphic.attributes[this.objectId]; + + require(["dojo/Deferred"], function (Deferred) { + deferred = new Deferred(); + + // Step 1 - lets see if record exits. If it does then return callback. + self.editExists(id).then(function (result) { + + // Step 4 - Then we check to see if the record actually exists or not. + deferred.then(function (result) { + + // IF the delete was successful, then the record should return 'false' because it doesn't exist. + self.editExists(id).then(function (results) { + callback(false); + }, + function (err) { + callback(true); //because we want this test to throw an error. That means item deleted. + }); + }, + // There was a problem with the delete operation on the database + function (err) { + callback(false, err); + }); + + var objectStore = db.transaction([self.objectStoreName], "readwrite").objectStore(self.objectStoreName); + + // Step 2 - go ahead and delete graphic + var objectStoreDeleteRequest = objectStore.delete(id); + + // Step 3 - We know that the onsuccess will always fire unless something serious goes wrong. + // So we go ahead and resolve the deferred here. + objectStoreDeleteRequest.onsuccess = function () { + deferred.resolve(true); + }; + + objectStoreDeleteRequest.onerror = function (msg) { + deferred.reject({success: false, error: msg}); + }; + + }, + // If there is an error in editExists() + function (err) { + callback(false, err); + }); + }); + }; + + /** + * Full database reset. + * CAUTION! If some edits weren't successfully sent, then their record + * will still exist in the database. If you use this function you + * will also delete those records. + * @param callback boolean + */ + this.resetEditsQueue = function (callback) { + console.assert(this._db !== null, "indexeddb not initialized"); + + var request = this._db.transaction([this.objectStoreName], "readwrite") + .objectStore(this.objectStoreName) + .clear(); + request.onsuccess = function (event) { + setTimeout(function () { + callback(true); + }, 0); + }; + request.onerror = function (err) { + callback(false, err); + }; + }; + + this.pendingEditsCount = function (callback) { + console.assert(this._db !== null, "indexeddb not initialized"); + + var count = 0; + var id = this.FEATURE_LAYER_JSON_ID; + var fCollectionId = this.FEATURE_COLLECTION_ID; + + var transaction = this._db.transaction([this.objectStoreName], "readwrite"); + var objectStore = transaction.objectStore(this.objectStoreName); + objectStore.openCursor().onsuccess = function (evt) { + var cursor = evt.target.result; + if (cursor && cursor.value && cursor.value.id) { + if (cursor.value.id !== id && cursor.value.id !== fCollectionId) { + count++; + } + cursor.continue(); + } + else { + callback(count); + } + }; + }; + + /** + * Verify is an edit already exists in the database. Checks the objectId. + * @param id + * @returns {deferred} {success: boolean, error: message} + * @private + */ + this.editExists = function (id) { + + var db = this._db; + var deferred = null; + var self = this; + + require(["dojo/Deferred"], function (Deferred) { + deferred = new Deferred(); + + var objectStore = db.transaction([self.objectStoreName], "readwrite").objectStore(self.objectStoreName); + + //Get the entry associated with the graphic + var objectStoreGraphicRequest = objectStore.get(id); + + objectStoreGraphicRequest.onsuccess = function () { + var graphic = objectStoreGraphicRequest.result; + if (graphic && (graphic.id == id)) { + deferred.resolve({success: true, error: null}); + } + else { + deferred.reject({success: false, error: "objectId is not a match."}); + } + }; + + objectStoreGraphicRequest.onerror = function (msg) { + deferred.reject({success: false, error: msg}); + }; + }); + + //We return a deferred object so that when calling this function you can chain it with a then() statement. + return deferred; + }; + + /** + * Returns the approximate size of the database in bytes + * IMPORTANT: Currently requires all data be serialized! + * @param callback callback({usage}, error) Whereas, the usage Object is {sizeBytes: number, editCount: number} + */ + this.getUsage = function (callback) { + console.assert(this._db !== null, "indexeddb not initialized"); + + var id = this.FEATURE_LAYER_JSON_ID; + var fCollectionId = this.FEATURE_COLLECTION_ID; + + var usage = {sizeBytes: 0, editCount: 0}; + + var transaction = this._db.transaction([this.objectStoreName]) + .objectStore(this.objectStoreName) + .openCursor(); + + console.log("dumping keys"); + + transaction.onsuccess = function (event) { + var cursor = event.target.result; + if (cursor && cursor.value && cursor.value.id) { + var storedObject = cursor.value; + var json = JSON.stringify(storedObject); + usage.sizeBytes += json.length; + + if (cursor.value.id !== id && cursor.value.id !== fCollectionId) { + usage.editCount += 1; + } + + cursor.continue(); + } + else { + callback(usage, null); + } + }; + transaction.onerror = function (err) { + callback(null, err); + }; + }; + + this.init = function (callback) { + console.log("init editsStore.js"); + + var request = indexedDB.open(this.dbName, 11); + callback = callback || function (success) { + console.log("EditsStore::init() success:", success); + }.bind(this); + + request.onerror = function (event) { + console.log("indexedDB error: " + event.target.errorCode); + callback(false, event.target.errorCode); + }.bind(this); + + request.onupgradeneeded = function (event) { + var db = event.target.result; + + if (db.objectStoreNames.contains(this.objectStoreName)) { + db.deleteObjectStore(this.objectStoreName); + } + + db.createObjectStore(this.objectStoreName, {keyPath: "id"}); + }.bind(this); + + request.onsuccess = function (event) { + this._db = event.target.result; + this._isDBInit = true; + console.log("database opened successfully"); + callback(true, null); + }.bind(this); + }; +}; + + diff --git a/dist/offline-edit-min.js b/dist/offline-edit-min.js deleted file mode 100644 index d622a4a3..00000000 --- a/dist/offline-edit-min.js +++ /dev/null @@ -1,5 +0,0 @@ -/*! esri-offline-maps - v2.16.0 - 2015-10-29 -* Copyright (c) 2015 Environmental Systems Research Institute, Inc. -* Apache License*/ -define(["dojo/Evented","dojo/_base/Deferred","dojo/promise/all","dojo/_base/declare","dojo/_base/array","dojo/dom-attr","dojo/dom-style","dojo/query","esri/config","esri/layers/GraphicsLayer","esri/graphic","esri/request","esri/symbols/SimpleMarkerSymbol","esri/symbols/SimpleLineSymbol","esri/symbols/SimpleFillSymbol","esri/urlUtils"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p){"use strict";return d("O.esri.Edit.OfflineFeaturesManager",[a],{_onlineStatus:"online",_featureLayers:{},_featureCollectionUsageFlag:!1,_editStore:new O.esri.Edit.EditStore,_defaultXhrTimeout:15e3,ONLINE:"online",OFFLINE:"offline",RECONNECTING:"reconnecting",attachmentsStore:null,proxyPath:null,ENABLE_FEATURECOLLECTION:!1,DB_NAME:"features_store",DB_OBJECTSTORE_NAME:"features",DB_UID:"objectid",ATTACHMENTS_DB_NAME:"attachments_store",ATTACHMENTS_DB_OBJECTSTORE_NAME:"attachments",events:{EDITS_SENT:"edits-sent",EDITS_ENQUEUED:"edits-enqueued",EDITS_ENQUEUED_ERROR:"edits-enqueued-error",EDITS_SENT_ERROR:"edits-sent-error",ALL_EDITS_SENT:"all-edits-sent",ATTACHMENT_ENQUEUED:"attachment-enqueued",ATTACHMENTS_SENT:"attachments-sent",EXTEND_COMPLETE:"extend-complete"},initAttachments:function(a){if(a=a||function(a){},!this._checkFileAPIs())return a(!1,"File APIs not supported");try{if(this.attachmentsStore=new O.esri.Edit.AttachmentsStore,this.attachmentsStore.dbName=this.ATTACHMENTS_DB_NAME,this.attachmentsStore.objectStoreName=this.ATTACHMENTS_DB_OBJECTSTORE_NAME,!this.attachmentsStore.isSupported())return a(!1,"indexedDB not supported");this.attachmentsStore.init(a)}catch(b){}},extend:function(a,d,i){function l(){try{a._phantomLayer=new j({opacity:.8}),a._map.addLayer(a._phantomLayer)}catch(b){}}var m=[],n=this;a.offlineExtended=!0,!a.loaded||null===a._url,a.objectIdField=this.DB_UID;var o=null;a.url&&(o=a.url,this._featureLayers[a.url]=a),a._mode.featureLayer.hasOwnProperty("_collection")&&(this._featureCollectionUsageFlag=!0),this._editStore._isDBInit||m.push(this._initializeDB(i,o)),a._applyEdits=a.applyEdits,a._addAttachment=a.addAttachment,a._queryAttachmentInfos=a.queryAttachmentInfos,a._deleteAttachments=a.deleteAttachments,a._updateAttachment=a.updateAttachment,a.queryAttachmentInfos=function(a,c,d){if(n.getOnlineStatus()===n.ONLINE){var e=this._queryAttachmentInfos(a,function(){n.emit(n.events.ATTACHMENTS_INFO,arguments),c&&c.apply(this,arguments)},d);return e}if(n.attachmentsStore){var f=new b;return n.attachmentsStore.getAttachmentsByFeatureId(this.url,a,function(a){c&&c(a),f.resolve(a)}),f}},a.addAttachment=function(a,c,d,e){if(n.getOnlineStatus()===n.ONLINE)return this._addAttachment(a,c,function(){n.emit(n.events.ATTACHMENTS_SENT,arguments),d&&d.apply(this,arguments)},function(a){e&&e.apply(this,arguments)});if(n.attachmentsStore){var f=this._getFilesFromForm(c),g=f[0],i=new b,j=this._getNextTempId();return n.attachmentsStore.store(this.url,j,a,g,n.attachmentsStore.TYPE.ADD,function(b,c){var f={attachmentId:j,objectId:a,success:b};if(b){n.emit(n.events.ATTACHMENT_ENQUEUED,f),d&&d(f),i.resolve(f);var g=this._url.path+"/"+a+"/attachments/"+j,k=h("[href="+g+"]");k.attr("href",c.url)}else f.error="can't store attachment",e&&e(f),i.reject(f)}.bind(this)),i}},a.updateAttachment=function(a,c,d,e,f){if(n.getOnlineStatus()===n.ONLINE)return this._updateAttachment(a,c,d,function(){e&&e.apply(this,arguments)},function(a){f&&f.apply(this,arguments)});if(n.attachmentsStore){var g=this._getFilesFromForm(d),i=g[0],j=n.attachmentsStore.TYPE.UPDATE,k=new b;return 0>c&&(j=n.attachmentsStore.TYPE.ADD),n.attachmentsStore.store(this.url,c,a,i,j,function(b,d){var g={attachmentId:c,objectId:a,success:b};if(b){n.emit(n.events.ATTACHMENT_ENQUEUED,g),e&&e(g),k.resolve(g);var i=this._url.path+"/"+a+"/attachments/"+c,j=h("[href="+i+"]");j.attr("href",d.url)}else g.error="layer.updateAttachment::attachmentStore can't store attachment",f&&f(g),k.reject(g)}.bind(this)),k}},a.deleteAttachments=function(a,d,e,f){if(n.getOnlineStatus()===n.ONLINE){var g=this._deleteAttachments(a,d,function(){e&&e.apply(this,arguments)},function(a){f&&f.apply(this,arguments)});return g}if(n.attachmentsStore){var h=[];d.forEach(function(c){c=parseInt(c,10);var d=new b;if(0>c)n.attachmentsStore["delete"](c,function(b){var e={objectId:a,attachmentId:c,success:b};d.resolve(e)});else{var e=new Blob([],{type:"image/png"});n.attachmentsStore.store(this.url,c,a,e,n.attachmentsStore.TYPE.DELETE,function(b,e){var f={attachmentId:c,objectId:a,success:b};b?d.resolve(f):d.reject(f)}.bind(this))}h.push(d)},this);var i=c(h);return i.then(function(a){e&&e(a)}),i}},a.applyEdits=function(d,e,f,g,h){var i=[];if(n.getOnlineStatus()===n.ONLINE){var j=this._applyEdits(d,e,f,function(){n.emit(n.events.EDITS_SENT,arguments),g&&g.apply(this,arguments)},h);return j}var k=new b,l={addResults:[],updateResults:[],deleteResults:[]},m={},o=d||[];return o.forEach(function(a){var c=new b,d=this._getNextTempId();a.attributes[this.objectIdField]=d;var e=this;this._validateFeature(a,this.url,n._editStore.ADD).then(function(b){b.success?e._pushValidatedAddFeatureToDB(e,a,b.operation,l,d,c):c.resolve(!0)},function(a){c.reject(a)}),i.push(c)},this),e=e||[],e.forEach(function(a){var c=new b,d=a.attributes[this.objectIdField];m[d]=a;var e=this;this._validateFeature(a,this.url,n._editStore.UPDATE).then(function(b){b.success?e._pushValidatedUpdateFeatureToDB(e,a,b.operation,l,d,c):c.resolve(!0)},function(a){c.reject(a)}),i.push(c)},this),f=f||[],f.forEach(function(a){var c=new b,d=a.attributes[this.objectIdField],e=this;this._validateFeature(a,this.url,n._editStore.DELETE).then(function(b){b.success?e._pushValidatedDeleteFeatureToDB(e,a,b.operation,l,d,c):c.resolve(!0)},function(a){c.reject(a)}),i.push(c)},this),c(i).then(function(b){for(var c=!0,d=0;dg;g++){var h=a[g].toJson();if(f.push(h),g==e-1){var i=JSON.stringify(f),j=JSON.stringify(d);c(i,j);break}}},a.getFeatureLayerJSON=function(a,b){require(["esri/request"],function(c){var d=c({url:a,content:{f:"json"},handleAs:"json",callbackParamName:"callback"});d.then(function(a){b(!0,a)},function(a){b(!1,a.message)})})},a.setFeatureLayerJSONDataStore=function(a,b){n._editStore.pushFeatureLayerJSON(a,function(a,c){b(a,c)})},a.getFeatureLayerJSONDataStore=function(a){n._editStore.getFeatureLayerJSON(function(b,c){a(b,c)})},a.setPhantomLayerGraphics=function(a){var b=a.length;if(b>0)for(var c=0;b>c;c++){var d=new k(a[c]);this._phantomLayer.add(d)}},a.getPhantomLayerGraphics=function(b){for(var c=a._phantomLayer.graphics,d=a._phantomLayer.graphics.length,e=[],f=0;d>f;f++){var g=c[f].toJson();if(e.push(g),f==d-1){var h=JSON.stringify(e);b(h);break}}},a.getPhantomGraphicsArray=function(a){n._editStore.getPhantomGraphicsArray(function(b,c){"end"==c?a(!0,b):a(!1,c)})},a.getAttachmentsUsage=function(a){n.attachmentsStore.getUsage(function(b,c){a(b,c)})},a.resetAttachmentsDatabase=function(a){n.attachmentsStore.resetAttachmentsQueue(function(b,c){a(b,c)})},a.getUsage=function(a){n._editStore.getUsage(function(b,c){a(b,c)})},a.resetDatabase=function(a){n._editStore.resetEditsQueue(function(b,c){a(b,c)})},a.pendingEditsCount=function(a){n._editStore.pendingEditsCount(function(b){a(b)})},a.getFeatureDefinition=function(a,b,c,d){var e={layerDefinition:a,featureSet:{features:b,geometryType:c}};d(e)},a.getAllEditsArray=function(a){n._editStore.getAllEditsArray(function(b,c){"end"==c?a(!0,b):a(!1,c)})},a._pushFeatureCollections=function(b){n._editStore._getFeatureCollections(function(c,d){var e={featureLayerUrl:a.url,featureLayerCollection:a.toJson()},f=[e],g={id:n._editStore.FEATURE_COLLECTION_ID,featureCollections:f};if(a.hasAttachments=e.featureLayerCollection.layerDefinition.hasAttachments,c){for(var h=0,i=0;id;d++)n.attachmentsStore.replaceFeatureId(this.url,a[d],b[d],function(a){--f,g+=a?1:0,0===f&&c(g)}.bind(this))},a._nextTempId=-1,a._getNextTempId=function(){return this._nextTempId--},l(),c(m).then(function(b){0===b.length&&o?this.ENABLE_FEATURECOLLECTION?a._pushFeatureCollections(function(a){a?d(!0,null):d(!1,null)}):d(!0,null):b[0].success&&!o?this._editStore.getFeatureLayerJSON(function(b,c){b?(this._featureLayers[c.__featureLayerURL]=a,a.url=c.__featureLayerURL,this.ENABLE_FEATURECOLLECTION?a._pushFeatureCollections(function(a){a?d(!0,null):d(!1,null)}):d(!0,null)):d(!1,c)}.bind(this)):b[0].success&&(this.ENABLE_FEATURECOLLECTION?a._pushFeatureCollections(function(a){a?d(!0,null):d(!1,null)}):d(!0,null))}.bind(this))},goOffline:function(){this._onlineStatus=this.OFFLINE},goOnline:function(a){this._onlineStatus=this.RECONNECTING,this._replayStoredEdits(function(b,c){var d={success:b,responses:c};this._onlineStatus=this.ONLINE,null!=this.attachmentsStore?this._sendStoredAttachments(function(b,c,e){d.attachments={success:b,responses:c,dbResponses:e},a&&a(d)}.bind(this)):a&&a(d)}.bind(this))},getOnlineStatus:function(){return this._onlineStatus},serializeFeatureGraphicsArray:function(a,b){for(var c=a.length,d=[],e=0;c>e;e++){var f=a[e].toJson();if(d.push(f),e==c-1){var g=JSON.stringify(d);b(g);break}}},getFeatureCollections:function(a){this._editStore._isDBInit?this._editStore._getFeatureCollections(function(b,c){a(b,c)}):this._initializeDB(null,null).then(function(b){b.success&&this._editStore._getFeatureCollections(function(b,c){a(b,c)})}.bind(this),function(b){a(!1,b)})},getFeatureLayerJSONDataStore:function(a){this._editStore._isDBInit?this._editStore.getFeatureLayerJSON(function(b,c){a(b,c)}):this._initializeDB(null,null).then(function(b){b.success&&this._editStore.getFeatureLayerJSON(function(b,c){a(b,c)})}.bind(this),function(b){a(!1,b)})},_initializeDB:function(a,c){var d=new b,e=this._editStore;return e.dbName=this.DB_NAME,e.objectStoreName=this.DB_OBJECTSTORE_NAME,e.objectId=this.DB_UID,e.init(function(b,f){"object"==typeof a&&b===!0&&void 0!==a&&null!==a?(c&&(a.__featureLayerURL=c),e.pushFeatureLayerJSON(a,function(a,b){a?d.resolve({success:!0,error:null}):d.reject({success:!1,error:b})})):b?d.resolve({success:!0,error:null}):d.reject({success:!1,error:null})}),d},_checkFileAPIs:function(){return window.File&&window.FileReader&&window.FileList&&window.Blob?(XMLHttpRequest.prototype.sendAsBinary||(XMLHttpRequest.prototype.sendAsBinary=function(a){function b(a){return 255&a.charCodeAt(0)}var c=Array.prototype.map.call(a,b),d=new Uint8Array(c);this.send(d.buffer)}),!0):!1},_extendAjaxReq:function(a){a.sendAsBinary=XMLHttpRequest.prototype.sendAsBinary},_phantomSymbols:[],_getPhantomSymbol:function(a,b){if(0===this._phantomSymbols.length){var c=[0,255,0,255],d=1.5;this._phantomSymbols.point=[],this._phantomSymbols.point[this._editStore.ADD]=new m({type:"esriSMS",style:"esriSMSCross",xoffset:10,yoffset:10,color:[255,255,255,0],size:15,outline:{color:c,width:d,type:"esriSLS",style:"esriSLSSolid"}}),this._phantomSymbols.point[this._editStore.UPDATE]=new m({type:"esriSMS",style:"esriSMSCircle",xoffset:0,yoffset:0,color:[255,255,255,0],size:15,outline:{color:c,width:d,type:"esriSLS",style:"esriSLSSolid"}}),this._phantomSymbols.point[this._editStore.DELETE]=new m({type:"esriSMS",style:"esriSMSX",xoffset:0,yoffset:0,color:[255,255,255,0],size:15,outline:{color:c,width:d,type:"esriSLS",style:"esriSLSSolid"}}),this._phantomSymbols.multipoint=null,this._phantomSymbols.polyline=[],this._phantomSymbols.polyline[this._editStore.ADD]=new n({type:"esriSLS",style:"esriSLSSolid",color:c,width:d}),this._phantomSymbols.polyline[this._editStore.UPDATE]=new n({type:"esriSLS",style:"esriSLSSolid",color:c,width:d}),this._phantomSymbols.polyline[this._editStore.DELETE]=new n({type:"esriSLS",style:"esriSLSSolid",color:c,width:d}),this._phantomSymbols.polygon=[],this._phantomSymbols.polygon[this._editStore.ADD]=new o({type:"esriSFS",style:"esriSFSSolid",color:[255,255,255,0],outline:{type:"esriSLS",style:"esriSLSSolid",color:c,width:d}}),this._phantomSymbols.polygon[this._editStore.UPDATE]=new o({type:"esriSFS",style:"esriSFSSolid",color:[255,255,255,0],outline:{type:"esriSLS",style:"esriSLSDash",color:c,width:d}}),this._phantomSymbols.polygon[this._editStore.DELETE]=new o({type:"esriSFS",style:"esriSFSSolid",color:[255,255,255,0],outline:{type:"esriSLS",style:"esriSLSDot",color:c,width:d}})}return this._phantomSymbols[a.type][b]},_uploadAttachment:function(a){var c=new b,d=this._featureLayers[a.featureLayerUrl],e=new FormData;switch(e.append("attachment",a.file),a.type){case this.attachmentsStore.TYPE.ADD:d.addAttachment(a.objectId,e,function(b){c.resolve({attachmentResult:b,id:a.id})},function(a){c.reject(a)});break;case this.attachmentsStore.TYPE.UPDATE:e.append("attachmentId",a.id),d._sendAttachment("update",a.objectId,e,function(b){c.resolve({attachmentResult:b,id:a.id})},function(a){c.reject(a)});break;case this.attachmentsStore.TYPE.DELETE:d.deleteAttachments(a.objectId,[a.id],function(b){c.resolve({attachmentResult:b,id:a.id})},function(a){c.reject(a)})}return c.promise},_deleteAttachmentFromDB:function(a,c){var d=new b;return this.attachmentsStore["delete"](a,function(a){d.resolve({success:a,result:c})}),d},_cleanAttachmentsDB:function(a,b){var d=this,e=[],f=0;a.forEach(function(a){"object"==typeof a.attachmentResult&&a.attachmentResult.success?e.push(d._deleteAttachmentFromDB(a.id,null)):a.attachmentResult instanceof Array?a.attachmentResult.forEach(function(b){b.success?e.push(d._deleteAttachmentFromDB(a.id,null)):f++}):f++});var g=c(e);g.then(function(c){b(f>0?{errors:!0,attachmentsDBResults:c,uploadResults:a}:{errors:!1,attachmentsDBResults:c,uploadResults:a})})},_sendStoredAttachments:function(a){this.attachmentsStore.getAllAttachments(function(b){var d=this,e=[];b.forEach(function(a){var b=this._uploadAttachment(a);e.push(b)},this);var f=c(e);f.then(function(b){d._cleanAttachmentsDB(b,function(c){c.errors?a&&a(!1,b,c):a&&a(!0,b,c)})},function(b){a&&a(!1,b)})}.bind(this))},_replayStoredEdits:function(a){var b,d={},e=this,f=[],g=[],h=[],i=[],j=[],l=this._featureLayers,m=this.attachmentsStore,n=this._editStore;this._editStore.getAllEditsArray(function(o,p){if(o.length>0){j=o;for(var q=j.length,r=0;q>r;r++){b=l[j[r].layer],null==m&&b.hasAttachments,b._attachmentsStore=m,b.__onEditsComplete=b.onEditsComplete,b.onEditsComplete=function(){},f=[],g=[],h=[],i=[];var s=new k(j[r].graphic);switch(j[r].operation){case n.ADD:for(var t=0;t0&&(g.updateResults[0].success?(h.layer=g.layer,h.id=g.updateResults[0].objectId,d.push(h)):e.push(g)),g.deleteResults.length>0&&(g.deleteResults[0].success?(h.layer=g.layer,h.id=g.deleteResults[0].objectId,d.push(h)):e.push(g)),g.addResults.length>0&&(g.addResults[0].success?(h.layer=g.layer,h.id=g.tempId,d.push(h)):e.push(g))}for(var i={},j=d.length,k=0;j>k;k++)i[k]=this._updateDatabase(d[k]);var l=c(i);l.then(function(a){e.length>0?b(!1,a):b(!0,a)},function(a){b(!1,a)})}else b(!0,{})},_updateDatabase:function(a){var c=new b,d={};return d.attributes={},d.attributes[this.DB_UID]=a.id,this._editStore["delete"](a.layer,d,function(a,b){a?c.resolve({success:!0,error:null}):c.reject({success:!1,error:b})}.bind(this)),c.promise},getFeatureLayerJSON:function(a,b){require(["esri/request"],function(c){var d=c({url:a,content:{f:"json"},handleAs:"json",callbackParamName:"callback"});d.then(function(a){b(!0,a)},function(a){b(!1,a.message)})})},_internalApplyEdits:function(a,c,d,e,f,g){var h=this,i=new b;return a._applyEdits(e,f,g,function(b,e,f){if(a._phantomLayer.clear(),null!=a._attachmentsStore&&a.hasAttachments&&d.length>0){var g=b.map(function(a){return a.objectId});a._replaceFeatureIds(d,g,function(a){})}h._cleanDatabase(a,d,b,e,f).then(function(g){i.resolve({id:c,layer:a.url,tempId:d,addResults:b,updateResults:e,deleteResults:f,databaseResults:g,databaseErrors:null})},function(g){i.resolve({id:c,layer:a.url,tempId:d,addResults:b,updateResults:e,deleteResults:f,databaseResults:null,databaseErrors:g})})},function(b){a.onEditsComplete=a.__onEditsComplete,delete a.__onEditsComplete,i.reject(b)}),i.promise},_internalApplyEditsAll:function(a,c,d,e,f,g){var h=this,i=new b;return this._makeEditRequest(a,e,f,g,function(b,f,g){if(a._phantomLayer.clear(),null!=a._attachmentsStore&&a.hasAttachments&&d.length>0){var j=b.map(function(a){return a.objectId});a._replaceFeatureIds(d,j,function(a){})}if(b.length>0){var l=new k(e[0].geometry,null,e[0].attributes);a.add(l)}h._cleanDatabase(a,d,b,f,g).then(function(e){i.resolve({id:c,layer:a.url,tempId:d,addResults:b,updateResults:f,deleteResults:g,databaseResults:e,databaseErrors:null,syncError:null})},function(e){i.resolve({id:c,layer:a.url,tempId:d,addResults:b,updateResults:f,deleteResults:g,databaseResults:null,databaseErrors:e,syncError:e})})},function(b){a.onEditsComplete=a.__onEditsComplete,delete a.__onEditsComplete,i.reject(b)}),i.promise},_cleanDatabase:function(a,c,d,e,f){var g=new b,h=null;e.length>0&&e[0].success&&(h=e[0].objectId),f.length>0&&f[0].success&&(h=f[0].objectId),d.length>0&&d[0].success&&(h=c);var i={};return i.attributes={},i.attributes[this.DB_UID]=h,this._editStore["delete"](a.url,i,function(a,b){if(a){var c=this._editStore.PHANTOM_GRAPHIC_PREFIX+this._editStore._PHANTOM_PREFIX_TOKEN+i.attributes[this.DB_UID];this._editStore.deletePhantomGraphic(c,function(a,b){a?g.resolve({success:!0,error:null,id:c}):g.reject({success:!1,error:b,id:c})})}else g.reject({success:!1,error:b,id:c})}.bind(this)),g.promise},_makeEditRequest:function(a,b,c,d,f,g){var h="f=json",i="",j="",k="";if(b.length>0&&(e.forEach(b,function(a){a.hasOwnProperty("infoTemplate")&&delete a.infoTemplate},this),i="&adds="+JSON.stringify(b)),c.length>0&&(e.forEach(c,function(a){a.hasOwnProperty("infoTemplate")&&delete a.infoTemplate},this),j="&updates="+JSON.stringify(c)),d.length>0){var l=d[0].attributes[this.DB_UID];k="&deletes="+l}var m=h+i+j+k;a.hasOwnProperty("credential")&&a.credential&&a.credential.hasOwnProperty("token")&&a.credential.token&&(m=m+"&token="+a.credential.token);var n=new XMLHttpRequest;n.open("POST",a.url+"/applyEdits",!0),n.setRequestHeader("Content-type","application/x-www-form-urlencoded"),n.onload=function(){if(200===n.status&&""!==n.responseText)try{var a=JSON.parse(this.response);f(a.addResults,a.updateResults,a.deleteResults)}catch(b){g("Unable to parse xhr response",n)}},n.onerror=function(a){g(a)},n.ontimeout=function(){g("xhr timeout error")},n.timeout=this._defaultXhrTimeout,n.send(m)},_parseResponsesArray:function(a){var c=new b,d=0;for(var e in a)a.hasOwnProperty(e)&&(a[e].addResults.map(function(a){a.success||d++}),a[e].updateResults.map(function(a){a.success||d++}),a[e].deleteResults.map(function(a){a.success||d++}));return d>0?c.resolve(!1):c.resolve(!0),c.promise}})}),"undefined"!=typeof O?O.esri.Edit={}:(O={},O.esri={Edit:{}}),O.esri.Edit.EditStore=function(){"use strict";this._db=null,this._isDBInit=!1,this.dbName="features_store",this.objectStoreName="features",this.objectId="objectid",this.ADD="add",this.UPDATE="update",this.DELETE="delete",this.FEATURE_LAYER_JSON_ID="feature-layer-object-1001",this.FEATURE_COLLECTION_ID="feature-collection-object-1001",this.PHANTOM_GRAPHIC_PREFIX="phantom-layer",this._PHANTOM_PREFIX_TOKEN="|@|",this.isSupported=function(){return window.indexedDB?!0:!1},this.pushEdit=function(a,b,c,d){var e={id:b+"/"+c.attributes[this.objectId],operation:a,layer:b,type:c.geometry.type,graphic:c.toJson()};if("undefined"==typeof c.attributes[this.objectId])d(!1,"editsStore.pushEdit() - failed to insert undefined objectId into database. Did you set offlineFeaturesManager.DB_UID? "+JSON.stringify(c.attributes));else{var f=this._db.transaction([this.objectStoreName],"readwrite");f.oncomplete=function(a){d(!0)},f.onerror=function(a){d(!1,a.target.error.message)};var g=f.objectStore(this.objectStoreName);g.put(e)}},this.pushFeatureLayerJSON=function(a,b){"object"!=typeof a&&b(!1,"dataObject type is not an object.");var c=this._db;a.id=this.FEATURE_LAYER_JSON_ID,this.getFeatureLayerJSON(function(d,e){var f;if(d&&"undefined"!=typeof e){f=c.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName);for(var g in a)a.hasOwnProperty(g)&&(e[g]=a[g]);var h=f.put(e);h.onsuccess=function(){b(!0,null)},h.onerror=function(a){b(!1,a)}}else{var i=c.transaction([this.objectStoreName],"readwrite");i.oncomplete=function(a){b(!0,null)},i.onerror=function(a){b(!1,a.target.error.message)},f=i.objectStore(this.objectStoreName);try{f.put(a)}catch(j){b(!1,JSON.stringify(j))}}}.bind(this))},this.getFeatureLayerJSON=function(a){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName),c=b.get(this.FEATURE_LAYER_JSON_ID);c.onsuccess=function(){var b=c.result;"undefined"!=typeof b?a(!0,b):a(!1,"nothing found")},c.onerror=function(b){a(!1,b)}},this.deleteFeatureLayerJSON=function(a){var b=this._db,c=null,d=this,e=this.FEATURE_LAYER_JSON_ID;require(["dojo/Deferred"],function(f){c=new f,c.then(function(b){d.editExists(e).then(function(b){a(!1,{message:"object was not deleted."})},function(b){a(!0,{message:"id does not exist"})})},function(b){a(!1,{message:"id does not exist"})}),d.editExists(e).then(function(a){var f=b.transaction([d.objectStoreName],"readwrite").objectStore(d.objectStoreName),g=f["delete"](e);g.onsuccess=function(){c.resolve(!0)},g.onerror=function(a){c.reject({success:!1,error:a})}},function(a){c.reject({success:!1,message:a})}.bind(this))})},this.pushPhantomGraphic=function(a,b){var c=this._db,d=this.PHANTOM_GRAPHIC_PREFIX+this._PHANTOM_PREFIX_TOKEN+a.attributes[this.objectId],e={id:d,graphic:a.toJson()},f=c.transaction([this.objectStoreName],"readwrite");f.oncomplete=function(a){b(!0,null)},f.onerror=function(a){b(!1,a.target.error.message)};var g=f.objectStore(this.objectStoreName);g.put(e)},this.getPhantomGraphicsArray=function(a){var b=[];if(null!==this._db){var c=this.PHANTOM_GRAPHIC_PREFIX,d=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor();d.onsuccess=function(d){var e=d.target.result;e&&e.value&&e.value.id?(-1!=e.value.id.indexOf(c)&&b.push(e.value),e["continue"]()):a(b,"end")}.bind(this),d.onerror=function(b){a(null,b)}}else a(null,"no db")},this._getPhantomGraphicsArraySimple=function(a){var b=[];if(null!==this._db){var c=this.PHANTOM_GRAPHIC_PREFIX,d=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor();d.onsuccess=function(d){var e=d.target.result;e&&e.value&&e.value.id?(-1!=e.value.id.indexOf(c)&&b.push(e.value.id),e["continue"]()):a(b,"end")}.bind(this),d.onerror=function(b){a(null,b)}}else a(null,"no db")},this.deletePhantomGraphic=function(a,b){var c=this._db,d=null,e=this;require(["dojo/Deferred"],function(f){d=new f,e.editExists(a).then(function(f){d.then(function(c){e.editExists(a).then(function(a){b(!1,"item was not deleted")},function(a){b(!0,"item successfully deleted")})},function(a){b(!1,a)});var g=c.transaction([e.objectStoreName],"readwrite").objectStore(e.objectStoreName),h=g["delete"](a);h.onsuccess=function(){d.resolve(!0)},h.onerror=function(a){d.reject({success:!1,error:a})}},function(a){b(!1,"item doesn't exist in db")})})},this.resetLimitedPhantomGraphicsQueue=function(a,b){if(Object.keys(a).length>0){var c=this._db,d=0,e=c.transaction([this.objectStoreName],"readwrite"),f=e.objectStore(this.objectStoreName);f.onerror=function(){d++},e.oncomplete=function(){b(0===d?!0:!1)};for(var g in a)if(a.hasOwnProperty(g)){var h=a[g],i=this.PHANTOM_GRAPHIC_PREFIX+this._PHANTOM_PREFIX_TOKEN+h.id;h.updateResults.length>0&&h.updateResults[0].success&&f["delete"](i),h.deleteResults.length>0&&h.deleteResults[0].success&&f["delete"](i),h.addResults.length>0&&h.addResults[0].success&&f["delete"](i)}}else b(!0)},this.resetPhantomGraphicsQueue=function(a){var b=this._db;this._getPhantomGraphicsArraySimple(function(c){if(c!=[]){var d=0,e=b.transaction([this.objectStoreName],"readwrite"),f=e.objectStore(this.objectStoreName);f.onerror=function(){d++},e.oncomplete=function(){a(0===d?!0:!1)};for(var g=c.length,h=0;g>h;h++)f["delete"](c[h])}else a(!0)}.bind(this))},this.getEdit=function(a,b){var c=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName);if("undefined"==typeof a)return void b(!1,"id is undefined.");var d=c.get(a);d.onsuccess=function(){var c=d.result;c&&c.id==a?b(!0,c):b(!1,"Id not found")},d.onerror=function(a){b(!1,a)}},this.getAllEdits=function(a){if(null!==this._db){var b=this.FEATURE_LAYER_JSON_ID,c=this.FEATURE_COLLECTION_ID,d=this.PHANTOM_GRAPHIC_PREFIX,e=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor();e.onsuccess=function(e){var f=e.target.result;f&&f.hasOwnProperty("value")&&f.value.hasOwnProperty("id")?(f.value.id!==b&&f.value.id!==c&&-1==f.value.id.indexOf(d)&&a(f.value,null),f["continue"]()):a(null,"end")}.bind(this),e.onerror=function(b){a(null,b)}}else a(null,"no db")},this.getAllEditsArray=function(a){var b=[];if(null!==this._db){var c=this.FEATURE_LAYER_JSON_ID,d=this.FEATURE_COLLECTION_ID,e=this.PHANTOM_GRAPHIC_PREFIX,f=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor();f.onsuccess=function(f){var g=f.target.result;g&&g.value&&g.value.id?(g.value.id!==c&&g.value.id!==d&&-1==g.value.id.indexOf(e)&&b.push(g.value),g["continue"]()):a(b,"end")}.bind(this),f.onerror=function(b){a(null,b)}}else a(null,"no db")},this.updateExistingEdit=function(a,b,c,d){var e=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName),f=e.get(c.attributes[this.objectId]);f.onsuccess=function(){f.result;var g={id:b+"/"+c.attributes[this.objectId],operation:a,layer:b,graphic:c.toJson()},h=e.put(g);h.onsuccess=function(){d(!0)},h.onerror=function(a){d(!1,a)}}.bind(this)},this["delete"]=function(a,b,c){var d=this._db,e=null,f=this,g=a+"/"+b.attributes[this.objectId];require(["dojo/Deferred"],function(a){e=new a,f.editExists(g).then(function(a){e.then(function(a){f.editExists(g).then(function(a){c(!1)},function(a){c(!0)})},function(a){c(!1,a)});var b=d.transaction([f.objectStoreName],"readwrite").objectStore(f.objectStoreName),h=b["delete"](g);h.onsuccess=function(){e.resolve(!0)},h.onerror=function(a){e.reject({success:!1,error:a})}},function(a){c(!1)})})},this.resetEditsQueue=function(a){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear();b.onsuccess=function(b){setTimeout(function(){a(!0)},0)},b.onerror=function(b){a(!1,b)}},this.pendingEditsCount=function(a){var b=0,c=this.FEATURE_LAYER_JSON_ID,d=this.FEATURE_COLLECTION_ID,e=this.PHANTOM_GRAPHIC_PREFIX,f=this._db.transaction([this.objectStoreName],"readwrite"),g=f.objectStore(this.objectStoreName);g.openCursor().onsuccess=function(f){var g=f.target.result;g&&g.value&&g.value.id&&-1==g.value.id.indexOf(e)?(g.value.id!==c&&g.value.id!==d&&b++,g["continue"]()):a(b)}},this.editExists=function(a){var b=this._db,c=null,d=this;return require(["dojo/Deferred"],function(e){c=new e;var f=b.transaction([d.objectStoreName],"readwrite").objectStore(d.objectStoreName),g=f.get(a);g.onsuccess=function(){var b=g.result;b&&b.id==a?c.resolve({success:!0,error:null}):c.reject({success:!1,error:"objectId is not a match."})},g.onerror=function(a){c.reject({success:!1,error:a})}}),c},this.getUsage=function(a){var b=this.FEATURE_LAYER_JSON_ID,c=this.FEATURE_COLLECTION_ID,d=this.PHANTOM_GRAPHIC_PREFIX,e={sizeBytes:0,editCount:0},f=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor();f.onsuccess=function(f){var g=f.target.result;if(g&&g.value&&g.value.id){var h=g.value,i=JSON.stringify(h);e.sizeBytes+=i.length,-1==g.value.id.indexOf(d)&&g.value.id!==b&&g.value.id!==c&&(e.editCount+=1), -g["continue"]()}else a(e,null)},f.onerror=function(b){a(null,b)}},this._pushFeatureCollections=function(a,b){var c=this._db.transaction([this.objectStoreName],"readwrite");c.oncomplete=function(a){b(!0)},c.onerror=function(a){b(!1,a.target.error.message)};var d=c.objectStore(this.objectStoreName);d.put(a)},this._getFeatureCollections=function(a){var b=this._db.transaction([this.objectStoreName],"readonly").objectStore(this.objectStoreName),c=b.get(this.FEATURE_COLLECTION_ID);c.onsuccess=function(){var b=c.result;"undefined"!=typeof b?a(!0,b):a(!1,null)},c.onerror=function(b){a(!1,b)}},this._serialize=function(a){var b=a.toJson(),c={attributes:b.attributes,geometry:b.geometry,infoTemplate:b.infoTemplate,symbol:b.symbol};return JSON.stringify(c)},this._deserialize=function(a){var b;return require(["esri/graphic"],function(c){b=new c(JSON.parse(a))}),b},this.init=function(a){var b=indexedDB.open(this.dbName,11);a=a||function(a){}.bind(this),b.onerror=function(b){a(!1,b.target.errorCode)}.bind(this),b.onupgradeneeded=function(a){var b=a.target.result;b.objectStoreNames.contains(this.objectStoreName)&&b.deleteObjectStore(this.objectStoreName),b.createObjectStore(this.objectStoreName,{keyPath:"id"})}.bind(this),b.onsuccess=function(b){this._db=b.target.result,this._isDBInit=!0,a(!0,null)}.bind(this)}},O.esri.Edit.AttachmentsStore=function(){"use strict";this._db=null,this.dbName="attachments_store",this.objectStoreName="attachments",this.TYPE={ADD:"add",UPDATE:"update",DELETE:"delete"},this.isSupported=function(){return window.indexedDB?!0:!1},this.store=function(a,b,c,d,e,f){try{e==this.TYPE.ADD||e==this.TYPE.UPDATE||e==this.TYPE.DELETE?this._readFile(d,function(g,h){if(g){var i={id:b,objectId:c,type:e,featureId:a+"/"+c,contentType:d.type,name:d.name,size:d.size,featureLayerUrl:a,content:h,file:d},j=this._db.transaction([this.objectStoreName],"readwrite");j.oncomplete=function(a){f(!0,i)},j.onerror=function(a){f(!1,a.target.error.message)};try{j.objectStore(this.objectStoreName).put(i)}catch(k){f(!1,k)}}else f(!1,h)}.bind(this)):f(!1,"attachmentsStore.store() Invalid type in the constructor!")}catch(g){f(!1,g.stack)}},this.retrieve=function(a,b){var c=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName),d=c.get(a);d.onsuccess=function(a){var c=a.target.result;c?b(!0,c):b(!1,"not found")},d.onerror=function(a){b(!1,a)}},this.getAttachmentsByFeatureId=function(a,b,c){var d=a+"/"+b,e=[],f=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName),g=f.index("featureId"),h=IDBKeyRange.only(d);g.openCursor(h).onsuccess=function(a){var b=a.target.result;b?(e.push(b.value),b["continue"]()):c(e)}},this.getAttachmentsByFeatureLayer=function(a,b){var c=[],d=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName),e=d.index("featureLayerUrl"),f=IDBKeyRange.only(a);e.openCursor(f).onsuccess=function(a){var d=a.target.result;d?(c.push(d.value),d["continue"]()):b(c)}},this.getAllAttachments=function(a){var b=[],c=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName);c.openCursor().onsuccess=function(c){var d=c.target.result;d?(b.push(d.value),d["continue"]()):a(b)}},this.deleteAttachmentsByFeatureId=function(a,b,c){var d=a+"/"+b,e=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName),f=e.index("featureId"),g=IDBKeyRange.only(d),h=0;f.openCursor(g).onsuccess=function(a){var b=a.target.result;b?(e["delete"](b.primaryKey),h++,b["continue"]()):setTimeout(function(){c(h)},0)}.bind(this)},this["delete"]=function(a,b){this.retrieve(a,function(c,d){if(!c)return void b(!1,"attachment "+a+" not found");var e=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName)["delete"](a);e.onsuccess=function(a){setTimeout(function(){b(!0)},0)},e.onerror=function(a){b(!1,a)}}.bind(this))},this.deleteAll=function(a){this.getAllAttachments(function(b){var c=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear();c.onsuccess=function(b){setTimeout(function(){a(!0)},0)},c.onerror=function(b){a(!1,b)}}.bind(this))},this.replaceFeatureId=function(a,b,c,d){var e=a+"/"+b,f=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName),g=f.index("featureId"),h=IDBKeyRange.only(e),i=0;g.openCursor(h).onsuccess=function(b){var e=b.target.result;if(e){var g=a+"/"+c,h=e.value;h.featureId=g,h.objectId=c,f.put(h),i++,e["continue"]()}else setTimeout(function(){d(i)},1)}},this.getUsage=function(a){var b={sizeBytes:0,attachmentCount:0},c=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor();c.onsuccess=function(c){var d=c.target.result;if(d){var e=d.value,f=JSON.stringify(e);b.sizeBytes+=f.length,b.attachmentCount+=1,d["continue"]()}else a(b,null)}.bind(this),c.onerror=function(b){a(null,b)}},this.resetAttachmentsQueue=function(a){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear();b.onsuccess=function(b){setTimeout(function(){a(!0)},0)},b.onerror=function(b){a(!1,b)}},this._readFile=function(a,b){var c=new FileReader;c.onload=function(a){b(!0,a.target.result)},c.onerror=function(a){b(!1,a.target.result)},c.readAsBinaryString(a)},this.init=function(a){var b=indexedDB.open(this.dbName,12);a=a||function(a){}.bind(this),b.onerror=function(b){a(!1,b.target.errorCode)}.bind(this),b.onupgradeneeded=function(a){var b=a.target.result;b.objectStoreNames.contains(this.objectStoreName)&&b.deleteObjectStore(this.objectStoreName);var c=b.createObjectStore(this.objectStoreName,{keyPath:"id"});c.createIndex("featureId","featureId",{unique:!1}),c.createIndex("featureLayerUrl","featureLayerUrl",{unique:!1})}.bind(this),b.onsuccess=function(b){this._db=b.target.result,a(!0)}.bind(this)}}; \ No newline at end of file diff --git a/dist/offline-tiles-advanced-min.js b/dist/offline-tiles-advanced-min.js index fde704bc..5e24e446 100644 --- a/dist/offline-tiles-advanced-min.js +++ b/dist/offline-tiles-advanced-min.js @@ -1,5 +1,92 @@ -/*! esri-offline-maps - v2.16.0 - 2015-10-29 +/*! esri-offline-maps - v3.0.0 - 2015-11-23 * Copyright (c) 2015 Environmental Systems Research Institute, Inc. * Apache License*/ -define(["dojo/query","dojo/request","dojo/_base/declare","esri/layers/LOD","esri/geometry/Point","esri/geometry/Extent","esri/layers/TileInfo","esri/SpatialReference","esri/geometry/Polygon","esri/layers/TiledMapServiceLayer"],function(a,b,c,d,e,f,g,h,i,j){"use strict";return c("O.esri.Tiles.OfflineTileEnablerLayer",[j],{tileInfo:null,_imageType:"",_level:null,_minZoom:null,_maxZoom:null,_tilesCore:null,_secure:!1,constructor:function(a,b,c,d){this._isLocalStorage()===!1?(alert("OfflineTiles Library not supported on this browser."),b(!1)):window.localStorage.offline_id_manager="",void 0===d||null===d?(this.DB_NAME="offline_tile_store",this.DB_OBJECTSTORE_NAME="tilepath"):(this.DB_NAME=d.dbName,this.DB_OBJECTSTORE_NAME=d.objectStoreName),this._tilesCore=new O.esri.Tiles.TilesCore,Array.prototype.sortNumber=function(){return this.sort(function(a,b){return a-b})},this._self=this,this._lastTileUrl="",this._imageType="",this._getTileUrl=this.getTileUrl;var e=!0;return("undefined"!=typeof c||null!=c)&&(e=c),this.showBlankTiles=!0,this.offline={online:e,store:new O.esri.Tiles.TilesStore,proxyPath:null},this.offline.store.isSupported()?(this.offline.store.dbName=this.DB_NAME,this.offline.store.objectStoreName=this.DB_OBJECTSTORE_NAME,this.offline.store.init(function(c){c&&this._getTileInfoPrivate(a,function(a){b(a)})}.bind(this._self)),void 0):b(!1,"indexedDB not supported")},getTileUrl:function(b,c,d){this._level=b;var e,f=this,g=window.localStorage.offline_id_manager;if(void 0===g||""===g)e="";else{var h=JSON.parse(g);h.credentials.forEach(function(a){-1!==f.url.indexOf(a.server)&&(e="?token="+a.token)})}var i=this.url+"/tile/"+b+"/"+c+"/"+d+e;if(this.offline.online)return this._lastTileUrl=i,i;i=i.split("?")[0];var j="void:/"+b+"/"+c+"/"+d,k=null;return this._tilesCore._getTiles(k,this._imageType,i,j,this.offline.store,a,this.showBlankTiles),j},getBasemapLayer:function(a){var b=a.layerIds[0];return a.getLayer(b)},getLevelEstimation:function(a,b,c){var d=new O.esri.Tiles.TilingScheme(this),e=d.getAllCellIdsInExtent(a,b),f={level:b,tileCount:e.length,sizeBytes:e.length*c};return f},getLevel:function(){return this._level},getMaxZoom:function(a){null==this._maxZoom&&(this._maxZoom=this.tileInfo.lods[this.tileInfo.lods.length-1].level),a(this._maxZoom)},getMinZoom:function(a){null==this._minZoom&&(this._minZoom=this.tileInfo.lods[0].level),a(this._minZoom)},getMinMaxLOD:function(a,b){var c={},d=this.getMap(),e=d.getLevel()-Math.abs(a),f=d.getLevel()+b;return null!=this._maxZoom&&null!=this._minZoom?(c.max=Math.min(this._maxZoom,f),c.min=Math.max(this._minZoom,e)):(this.getMinZoom(function(a){c.min=Math.max(a,e)}),this.getMaxZoom(function(a){c.max=Math.min(a,f)})),c},prepareForOffline:function(a,b,c,d){this._tilesCore._createCellsForOffline(this,a,b,c,function(a){this._doNextTile(0,a,d)}.bind(this))},goOffline:function(){this.offline.online=!1},goOnline:function(){this.offline.online=!0,this.refresh()},isOnline:function(){return this.offline.online},deleteAllTiles:function(a){var b=this.offline.store;b.deleteAll(a)},getOfflineUsage:function(a){var b=this.offline.store;b.usedSpace(a)},getTilePolygons:function(a){this._tilesCore._getTilePolygons(this.offline.store,this.url,this,a)},saveToFile:function(a,b){this._tilesCore._saveToFile(a,this.offline.store,b)},loadFromFile:function(a,b){this._tilesCore._loadFromFile(a,this.offline.store,b)},estimateTileSize:function(a){this._tilesCore._estimateTileSize(b,this._lastTileUrl,this.offline.proxyPath,a)},getExtentBuffer:function(a,b){return b.xmin-=a,b.ymin-=a,b.xmax+=a,b.ymax+=a,b},getTileUrlsByExtent:function(a,b){var c=new O.esri.Tiles.TilingScheme(this),d=c.getAllCellIdsInExtent(a,b),e=[];return d.forEach(function(a){e.push(this.url+"/"+b+"/"+a[1]+"/"+a[0])}.bind(this)),e},_doNextTile:function(a,b,c){var d=b[a],e=this._getTileUrl(d.level,d.row,d.col);this._tilesCore._storeTile(e,this.offline.proxyPath,this.offline.store,function(e,f){e||(f={cell:d,msg:f});var g=c({countNow:a,countMax:b.length,cell:d,error:f,finishedDownloading:!1});g||a===b.length-1?c({finishedDownloading:!0,cancelRequested:g}):this._doNextTile(a+1,b,c)}.bind(this))},_isLocalStorage:function(){var a="test";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(b){return!1}},_parseTileInfo:function(a,b,c){b.offline.online===!1&&a===!1&&void 0!==localStorage.__offlineTileInfo?a=localStorage.__offlineTileInfo:b.offline.online===!1&&a===!1&&void 0===localStorage.__offlineTileInfo&&alert("There was a problem retrieving tiled map info in OfflineTilesEnablerLayer."),b._tilesCore._parseGetTileInfo(a,function(a){b.layerInfos=a.resultObj.layers,b.minScale=a.resultObj.minScale,b.maxScale=a.resultObj.maxScale,b.tileInfo=a.tileInfo,b._imageType=b.tileInfo.format.toLowerCase(),b.fullExtent=a.fullExtent,b.spatialReference=b.tileInfo.spatialReference,b.initialExtent=a.initExtent,b.loaded=!0,b.onLoad(b),c(!0)})},_getTileInfoPrivate:function(a,b){var c,d=this,e=new XMLHttpRequest,f=window.localStorage.offline_id_manager;if(void 0===f||""===f)c="";else{var g=JSON.parse(f);g.credentials.forEach(function(b){-1!==a.indexOf(b.server)&&(c="&token="+b.token)})}var h=null!=d.offline.proxyPath?d.offline.proxyPath+"?"+a+"?f=pjson"+c:a+"?f=pjson"+c;e.open("GET",h,!0),e.onload=function(){if(200===e.status&&""!==e.responseText){var c=this.response,f=this.response.replace(/\\'/g,"'"),g=JSON.parse(f);"error"in g?"code"in g.error&&(499==g.error.code||498==g.error.code)&&require(["esri/IdentityManager"],function(c){var e=c.findCredential(a);void 0===e?c.getCredential(a).then(function(){d._secure=!0,window.localStorage.offline_id_manager=JSON.stringify(c.toJson()),d._getTileInfoPrivate(a,b)}):d._getTileInfoPrivate(a,b)}):d._parseTileInfo(c,d,b)}else b(!1)},e.onerror=function(a){b(!1)},e.send(null)}})}),"undefined"!=typeof O?O.esri.Tiles={}:(O={},O.esri={Tiles:{}}),O.esri.Tiles.Base64Utils={},O.esri.Tiles.Base64Utils.outputTypes={Base64:0,Hex:1,String:2,Raw:3},O.esri.Tiles.Base64Utils.addWords=function(a,b){var c=(65535&a)+(65535&b),d=(a>>16)+(b>>16)+(c>>16);return d<<16|65535&c},O.esri.Tiles.Base64Utils.stringToWord=function(a){for(var b=8,c=(1<e;e+=b)d[e>>5]|=(a.charCodeAt(e/b)&c)<e;e+=b)d.push(String.fromCharCode(a[e>>5]>>>e%32&c));return d.join("")},O.esri.Tiles.Base64Utils.wordToHex=function(a){for(var b="0123456789abcdef",c=[],d=0,e=4*a.length;e>d;d++)c.push(b.charAt(a[d>>2]>>d%4*8+4&15)+b.charAt(a[d>>2]>>d%4*8&15));return c.join("")},O.esri.Tiles.Base64Utils.wordToBase64=function(a){for(var b="=",c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",d=[],e=0,f=4*a.length;f>e;e+=3)for(var g=(a[e>>2]>>8*(e%4)&255)<<16|(a[e+1>>2]>>8*((e+1)%4)&255)<<8|a[e+2>>2]>>8*((e+2)%4)&255,h=0;4>h;h++)8*e+6*h>32*a.length?d.push(b):d.push(c.charAt(g>>6*(3-h)&63));return d.join("")},/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ -O.esri.Tiles.saveAs=function(a){"use strict";var b=a.document,c=function(){return a.URL||a.webkitURL||a},d=a.URL||a.webkitURL||a,e=b.createElementNS("http://www.w3.org/1999/xhtml","a"),f=!a.externalHost&&"download"in e,g=a.webkitRequestFileSystem,h=a.requestFileSystem||g||a.mozRequestFileSystem,i=function(b){(a.setImmediate||a.setTimeout)(function(){throw b},0)},j="application/octet-stream",k=0,l=[],m=function(){for(var a=l.length;a--;){var b=l[a];"string"==typeof b?d.revokeObjectURL(b):b.remove()}l.length=0},n=function(a,b,c){b=[].concat(b);for(var d=b.length;d--;){var e=a["on"+b[d]];if("function"==typeof e)try{e.call(a,c||a)}catch(f){i(f)}}},o=function(d,i){var m,o,p,q=this,r=d.type,s=!1,t=function(){var a=c().createObjectURL(d);return l.push(a),a},u=function(){n(q,"writestart progress write writeend".split(" "))},v=function(){(s||!m)&&(m=t(d)),o?o.location.href=m:window.open(m,"_blank"),q.readyState=q.DONE,u()},w=function(a){return function(){return q.readyState!==q.DONE?a.apply(this,arguments):void 0}},x={create:!0,exclusive:!1};if(q.readyState=q.INIT,i||(i="download"),f){m=t(d),b=a.document,e=b.createElementNS("http://www.w3.org/1999/xhtml","a"),e.href=m,e.download=i;var y=b.createEvent("MouseEvents");return y.initMouseEvent("click",!0,!1,a,0,0,0,0,0,!1,!1,!1,!1,0,null),e.dispatchEvent(y),q.readyState=q.DONE,void u()}return a.chrome&&r&&r!==j&&(p=d.slice||d.webkitSlice,d=p.call(d,0,d.size,j),s=!0),g&&"download"!==i&&(i+=".download"),(r===j||g)&&(o=a),h?(k+=d.size,void h(a.TEMPORARY,k,w(function(a){a.root.getDirectory("saved",x,w(function(a){var b=function(){a.getFile(i,x,w(function(a){a.createWriter(w(function(b){b.onwriteend=function(b){o.location.href=a.toURL(),l.push(a),q.readyState=q.DONE,n(q,"writeend",b)},b.onerror=function(){var a=b.error;a.code!==a.ABORT_ERR&&v()},"writestart progress write abort".split(" ").forEach(function(a){b["on"+a]=q["on"+a]}),b.write(d),q.abort=function(){b.abort(),q.readyState=q.DONE},q.readyState=q.WRITING}),v)}),v)};a.getFile(i,{create:!1},w(function(a){a.remove(),b()}),w(function(a){a.code===a.NOT_FOUND_ERR?b():v()}))}),v)}),v)):void v()},p=o.prototype,q=function(a,b){return new o(a,b)};return p.abort=function(){var a=this;a.readyState=a.DONE,n(a,"abort")},p.readyState=p.INIT=0,p.WRITING=1,p.DONE=2,p.error=p.onwritestart=p.onprogress=p.onwrite=p.onabort=p.onerror=p.onwriteend=null,a.addEventListener("unload",m,!1),q}(this.self||this.window||this.content),O.esri.Tiles.TilesCore=function(){this._getTiles=function(a,b,c,d,e,f,g){e.retrieve(c,function(c,e){a=f("img[src="+d+"]")[0];var h;return c?(a.style.borderColor="blue",h="data:image/"+b+";base64,"+e.img):g?(a.style.borderColor="green",h="data:image/png;base64,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pmk0TROPj48Hn3l4eIimaSJN06O3A4NJwDMxm82ibdtXo4D5fB6r1Sp+//4dz8/Pw5H+6ekpdrtdJEkS8/n8S/9f713ie3vaceo9x557QAB451Sgfyin34HKshweunk5HzAej2MymXz5+f9nbjJyI9L39Wu5XP55+XQZ39uxR4Z3u90wSXjqEV0wAjhjx47oaZq63Me/ZhIQBAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAAbAJQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAvqe/BwCeKjUweoA8pQAAAABJRU5ErkJggg=="):h="data:image/png;base64,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AwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDDwAwMBPAABGrpAUwAAAABJRU5ErkJggg==",a.style.visibility="visible",a.src=h,""})},this._storeTile=function(a,b,c,d){a=a.split("?")[0];var e=b?b+"?"+a:a,f=new XMLHttpRequest;f.open("GET",e,!0),f.overrideMimeType("text/plain; charset=x-user-defined"),f.onload=function(){if(200===f.status&&""!==f.responseText){var b=O.esri.Tiles.Base64Utils.wordToBase64(O.esri.Tiles.Base64Utils.stringToWord(this.responseText)),g={url:a,img:b};c.store(g,d)}else d(!1,f.status+" "+f.statusText+": "+f.response+" when downloading "+e)},f.onerror=function(a){d(!1,a)},f.send(null)},this._createCellsForOffline=function(a,b,c,d,e){for(var f=new O.esri.Tiles.TilingScheme(a),g=[],h=b;c>=h;h++){var i=f.getAllCellIdsInExtent(d,h);if(i.forEach(function(a){g.push({level:h,row:a[1],col:a[0]})}),g.length>5e3&&h!==c)break}e(g)},this._saveToFile=function(a,b,c){var d=[];d.push("url,img"),b.getAllTiles(function(b,e,f){if("end"===f){var g=new Blob([d.join("\r\n")],{type:"text/plain;charset=utf-8"}),h=O.esri.Tiles.saveAs(g,a);if(h.readyState===h.DONE)return h.error?c(!1,"Error saving file "+a):c(!0,"Saved "+(d.length-1)+" tiles ("+Math.floor(g.size/1024/1024*100)/100+" Mb) into "+a);h.onerror=function(){c(!1,"Error saving file "+a)},h.onwriteend=function(){c(!0,"Saved "+(d.length-1)+" tiles ("+Math.floor(g.size/1024/1024*100)/100+" Mb) into "+a)}}else d.push(b+","+e)})},this._estimateTileSize=function(a,b,c,d){if(b){var e,f=window.localStorage.offline_id_manager;if(void 0===f||""===f)e="";else{var g=JSON.parse(f);g.credentials.forEach(function(a){-1!==b.indexOf(a.server)&&(e="?token="+a.token)})}var h=c?c+"?"+b+e:b+e;a.get(h,{handleAs:"text/plain; charset=x-user-defined",headers:{"X-Requested-With":""},timeout:2e3}).then(function(a){var b=O.esri.Tiles.Base64Utils.wordToBase64(O.esri.Tiles.Base64Utils.stringToWord(a));d(b.length+h.length,null)},function(a){d(null,a)})}else d(NaN)},this._loadFromFile=function(a,b,c){if(window.File&&window.FileReader&&window.FileList&&window.Blob){var d=new FileReader;d.onload=function(d){var e,f,g=d.target.result,h=g.split("\r\n"),i=0;if("url,img"!==h[0])return c(!1,"File "+a.name+" doesn't contain tiles that can be loaded");for(var j=1;j=c;c++)for(d=i;j>=d;d++)k.push([c,d]);return k}}; \ No newline at end of file +define(["dojo/query","dojo/request","dojo/_base/declare","esri/layers/LOD","esri/geometry/Point","esri/geometry/Extent","esri/layers/TileInfo","esri/SpatialReference","esri/geometry/Polygon","esri/layers/TiledMapServiceLayer"],function(a,b,c,d,e,f,g,h,i,j){"use strict" +return c("O.esri.Tiles.OfflineTilesAdvanced",[j],{tileInfo:null,_imageType:"",_level:null,_minZoom:null,_maxZoom:null,_tilesCore:null,_secure:!1,constructor:function(a,b,c,d){this._isLocalStorage()===!1?(alert("OfflineTiles Library not supported on this browser."),b(!1)):window.localStorage.offline_id_manager="",void 0===d||null===d?(this.DB_NAME="offline_tile_store",this.DB_OBJECTSTORE_NAME="tilepath"):(this.DB_NAME=d.dbName,this.DB_OBJECTSTORE_NAME=d.objectStoreName),this._tilesCore=new O.esri.Tiles.TilesCore,Array.prototype.sortNumber=function(){return this.sort(function(a,b){return a-b})},this._self=this,this._lastTileUrl="",this._imageType="",this._getTileUrl=this.getTileUrl +var e=!0 +return("undefined"!=typeof c||null!=c)&&(e=c),this.showBlankTiles=!0,this.offline={online:e,store:new O.esri.Tiles.TilesStore,proxyPath:null},this.offline.store.isSupported()?(this.offline.store.dbName=this.DB_NAME,this.offline.store.objectStoreName=this.DB_OBJECTSTORE_NAME,this.offline.store.init(function(c){c&&this._getTileInfoPrivate(a,function(a){b(a)})}.bind(this._self)),void 0):b(!1,"indexedDB not supported")},getTileUrl:function(b,c,d){this._level=b +var e,f=this,g=window.localStorage.offline_id_manager +if(void 0===g||""===g)e="" +else{var h=JSON.parse(g) +h.credentials.forEach(function(a){-1!==f.url.indexOf(a.server)&&(e="?token="+a.token)})}var i=this.url+"/tile/"+b+"/"+c+"/"+d+e +if(this.offline.online)return this._lastTileUrl=i,i +i=i.split("?")[0] +var j="void:/"+b+"/"+c+"/"+d,k=null +return this._tilesCore._getTiles(k,this._imageType,i,j,this.offline.store,a,this.showBlankTiles),j},getBasemapLayer:function(a){var b=a.layerIds[0] +return a.getLayer(b)},getLevelEstimation:function(a,b,c){var d=new O.esri.Tiles.TilingScheme(this),e=d.getAllCellIdsInExtent(a,b),f={level:b,tileCount:e.length,sizeBytes:e.length*c} +return f},getLevel:function(){return this._level},getMaxZoom:function(a){null==this._maxZoom&&(this._maxZoom=this.tileInfo.lods[this.tileInfo.lods.length-1].level),a(this._maxZoom)},getMinZoom:function(a){null==this._minZoom&&(this._minZoom=this.tileInfo.lods[0].level),a(this._minZoom)},getMinMaxLOD:function(a,b){var c={},d=this.getMap(),e=d.getLevel()-Math.abs(a),f=d.getLevel()+b +return null!=this._maxZoom&&null!=this._minZoom?(c.max=Math.min(this._maxZoom,f),c.min=Math.max(this._minZoom,e)):(this.getMinZoom(function(a){c.min=Math.max(a,e)}),this.getMaxZoom(function(a){c.max=Math.min(a,f)})),c},prepareForOffline:function(a,b,c,d){this._tilesCore._createCellsForOffline(this,a,b,c,function(a){this._doNextTile(0,a,d)}.bind(this))},goOffline:function(){this.offline.online=!1},goOnline:function(){this.offline.online=!0,this.refresh()},isOnline:function(){return this.offline.online},deleteAllTiles:function(a){var b=this.offline.store +b.deleteAll(a)},getOfflineUsage:function(a){var b=this.offline.store +b.usedSpace(a)},getTilePolygons:function(a){this._tilesCore._getTilePolygons(this.offline.store,this.url,this,a)},saveToFile:function(a,b){this._tilesCore._saveToFile(a,this.offline.store,b)},loadFromFile:function(a,b){this._tilesCore._loadFromFile(a,this.offline.store,b)},estimateTileSize:function(a){this._tilesCore._estimateTileSize(b,this._lastTileUrl,this.offline.proxyPath,a)},getExtentBuffer:function(a,b){return b.xmin-=a,b.ymin-=a,b.xmax+=a,b.ymax+=a,b},getTileUrlsByExtent:function(a,b){var c=new O.esri.Tiles.TilingScheme(this),d=c.getAllCellIdsInExtent(a,b),e=[] +return d.forEach(function(a){e.push(this.url+"/"+b+"/"+a[1]+"/"+a[0])}.bind(this)),e},_doNextTile:function(a,b,c){var d=b[a],e=this._getTileUrl(d.level,d.row,d.col) +this._tilesCore._storeTile(e,this.offline.proxyPath,this.offline.store,function(e,f){e||(f={cell:d,msg:f}) +var g=c({countNow:a,countMax:b.length,cell:d,error:f,finishedDownloading:!1}) +g||a===b.length-1?c({finishedDownloading:!0,cancelRequested:g}):this._doNextTile(a+1,b,c)}.bind(this))},_isLocalStorage:function(){var a="test" +try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(b){return!1}},_parseTileInfo:function(a,b,c){b.offline.online===!1&&a===!1&&void 0!==localStorage.__offlineTileInfo?a=localStorage.__offlineTileInfo:b.offline.online===!1&&a===!1&&void 0===localStorage.__offlineTileInfo&&alert("There was a problem retrieving tiled map info in OfflineTilesEnablerLayer."),b._tilesCore._parseGetTileInfo(a,function(a){b.layerInfos=a.resultObj.layers,b.minScale=a.resultObj.minScale,b.maxScale=a.resultObj.maxScale,b.tileInfo=a.tileInfo,b._imageType=b.tileInfo.format.toLowerCase(),b.fullExtent=a.fullExtent,b.spatialReference=b.tileInfo.spatialReference,b.initialExtent=a.initExtent,b.loaded=!0,b.onLoad(b),c(!0)})},_getTileInfoPrivate:function(a,b){var c,d=this,e=new XMLHttpRequest,f=window.localStorage.offline_id_manager +if(void 0===f||""===f)c="" +else{var g=JSON.parse(f) +g.credentials.forEach(function(b){-1!==a.indexOf(b.server)&&(c="&token="+b.token)})}var h=null!=d.offline.proxyPath?d.offline.proxyPath+"?"+a+"?f=pjson"+c:a+"?f=pjson"+c +e.open("GET",h,!0),e.onload=function(){if(200===e.status&&""!==e.responseText){var c=this.response,f=this.response.replace(/\\'/g,"'"),g=JSON.parse(f) +"error"in g?"code"in g.error&&(499==g.error.code||498==g.error.code)&&require(["esri/IdentityManager"],function(c){var e=c.findCredential(a) +void 0===e?c.getCredential(a).then(function(){d._secure=!0,window.localStorage.offline_id_manager=JSON.stringify(c.toJson()),d._getTileInfoPrivate(a,b)}):d._getTileInfoPrivate(a,b)}):d._parseTileInfo(c,d,b)}else b(!1)},e.onerror=function(a){b(!1)},e.send(null)}})}),"undefined"!=typeof O?O.esri.Tiles={}:(O={},O.esri={Tiles:{}}),O.esri.Tiles.Base64Utils={},O.esri.Tiles.Base64Utils.outputTypes={Base64:0,Hex:1,String:2,Raw:3},O.esri.Tiles.Base64Utils.addWords=function(a,b){var c=(65535&a)+(65535&b),d=(a>>16)+(b>>16)+(c>>16) +return d<<16|65535&c},O.esri.Tiles.Base64Utils.stringToWord=function(a){for(var b=8,c=(1<e;e+=b)d[e>>5]|=(a.charCodeAt(e/b)&c)<e;e+=b)d.push(String.fromCharCode(a[e>>5]>>>e%32&c)) +return d.join("")},O.esri.Tiles.Base64Utils.wordToHex=function(a){for(var b="0123456789abcdef",c=[],d=0,e=4*a.length;e>d;d++)c.push(b.charAt(a[d>>2]>>d%4*8+4&15)+b.charAt(a[d>>2]>>d%4*8&15)) +return c.join("")},O.esri.Tiles.Base64Utils.wordToBase64=function(a){for(var b="=",c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",d=[],e=0,f=4*a.length;f>e;e+=3)for(var g=(a[e>>2]>>8*(e%4)&255)<<16|(a[e+1>>2]>>8*((e+1)%4)&255)<<8|a[e+2>>2]>>8*((e+2)%4)&255,h=0;4>h;h++)8*e+6*h>32*a.length?d.push(b):d.push(c.charAt(g>>6*(3-h)&63)) +return d.join("")},/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ +O.esri.Tiles.saveAs=function(a){"use strict" +var b=a.document,c=function(){return a.URL||a.webkitURL||a},d=a.URL||a.webkitURL||a,e=b.createElementNS("http://www.w3.org/1999/xhtml","a"),f=!a.externalHost&&"download"in e,g=a.webkitRequestFileSystem,h=a.requestFileSystem||g||a.mozRequestFileSystem,i=function(b){(a.setImmediate||a.setTimeout)(function(){throw b},0)},j="application/octet-stream",k=0,l=[],m=function(){for(var a=l.length;a--;){var b=l[a] +"string"==typeof b?d.revokeObjectURL(b):b.remove()}l.length=0},n=function(a,b,c){b=[].concat(b) +for(var d=b.length;d--;){var e=a["on"+b[d]] +if("function"==typeof e)try{e.call(a,c||a)}catch(f){i(f)}}},o=function(d,i){var m,o,p,q=this,r=d.type,s=!1,t=function(){var a=c().createObjectURL(d) +return l.push(a),a},u=function(){n(q,"writestart progress write writeend".split(" "))},v=function(){(s||!m)&&(m=t(d)),o?o.location.href=m:window.open(m,"_blank"),q.readyState=q.DONE,u()},w=function(a){return function(){return q.readyState!==q.DONE?a.apply(this,arguments):void 0}},x={create:!0,exclusive:!1} +if(q.readyState=q.INIT,i||(i="download"),f){m=t(d),b=a.document,e=b.createElementNS("http://www.w3.org/1999/xhtml","a"),e.href=m,e.download=i +var y=b.createEvent("MouseEvents") +return y.initMouseEvent("click",!0,!1,a,0,0,0,0,0,!1,!1,!1,!1,0,null),e.dispatchEvent(y),q.readyState=q.DONE,void u()}return a.chrome&&r&&r!==j&&(p=d.slice||d.webkitSlice,d=p.call(d,0,d.size,j),s=!0),g&&"download"!==i&&(i+=".download"),(r===j||g)&&(o=a),h?(k+=d.size,void h(a.TEMPORARY,k,w(function(a){a.root.getDirectory("saved",x,w(function(a){var b=function(){a.getFile(i,x,w(function(a){a.createWriter(w(function(b){b.onwriteend=function(b){o.location.href=a.toURL(),l.push(a),q.readyState=q.DONE,n(q,"writeend",b)},b.onerror=function(){var a=b.error +a.code!==a.ABORT_ERR&&v()},"writestart progress write abort".split(" ").forEach(function(a){b["on"+a]=q["on"+a]}),b.write(d),q.abort=function(){b.abort(),q.readyState=q.DONE},q.readyState=q.WRITING}),v)}),v)} +a.getFile(i,{create:!1},w(function(a){a.remove(),b()}),w(function(a){a.code===a.NOT_FOUND_ERR?b():v()}))}),v)}),v)):void v()},p=o.prototype,q=function(a,b){return new o(a,b)} +return p.abort=function(){var a=this +a.readyState=a.DONE,n(a,"abort")},p.readyState=p.INIT=0,p.WRITING=1,p.DONE=2,p.error=p.onwritestart=p.onprogress=p.onwrite=p.onabort=p.onerror=p.onwriteend=null,a.addEventListener("unload",m,!1),q}(this.self||this.window||this.content),O.esri.Tiles.TilesCore=function(){this._getTiles=function(a,b,c,d,e,f,g){e.retrieve(c,function(c,e){a=f("img[src="+d+"]")[0] +var h +return c?(a.style.borderColor="blue",h="data:image/"+b+";base64,"+e.img):g?(a.style.borderColor="green",h="data:image/png;base64,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pmk0TROPj48Hn3l4eIimaSJN06O3A4NJwDMxm82ibdtXo4D5fB6r1Sp+//4dz8/Pw5H+6ekpdrtdJEkS8/n8S/9f713ie3vaceo9x557QAB451Sgfyin34HKshweunk5HzAej2MymXz5+f9nbjJyI9L39Wu5XP55+XQZ39uxR4Z3u90wSXjqEV0wAjhjx47oaZq63Me/ZhIQBAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAAbAJQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAvqe/BwCeKjUweoA8pQAAAABJRU5ErkJggg=="):h="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAD8GlDQ1BJQ0MgUHJvZmlsZQAAOI2NVd1v21QUP4lvXKQWP6Cxjg4Vi69VU1u5GxqtxgZJk6XpQhq5zdgqpMl1bhpT1za2021Vn/YCbwz4A4CyBx6QeEIaDMT2su0BtElTQRXVJKQ9dNpAaJP2gqpwrq9Tu13GuJGvfznndz7v0TVAx1ea45hJGWDe8l01n5GPn5iWO1YhCc9BJ/RAp6Z7TrpcLgIuxoVH1sNfIcHeNwfa6/9zdVappwMknkJsVz19HvFpgJSpO64PIN5G+fAp30Hc8TziHS4miFhheJbjLMMzHB8POFPqKGKWi6TXtSriJcT9MzH5bAzzHIK1I08t6hq6zHpRdu2aYdJYuk9Q/881bzZa8Xrx6fLmJo/iu4/VXnfH1BB/rmu5ScQvI77m+BkmfxXxvcZcJY14L0DymZp7pML5yTcW61PvIN6JuGr4halQvmjNlCa4bXJ5zj6qhpxrujeKPYMXEd+q00KR5yNAlWZzrF+Ie+uNsdC/MO4tTOZafhbroyXuR3Df08bLiHsQf+ja6gTPWVimZl7l/oUrjl8OcxDWLbNU5D6JRL2gxkDu16fGuC054OMhclsyXTOOFEL+kmMGs4i5kfNuQ62EnBuam8tzP+Q+tSqhz9SuqpZlvR1EfBiOJTSgYMMM7jpYsAEyqJCHDL4dcFFTAwNMlFDUUpQYiadhDmXteeWAw3HEmA2s15k1RmnP4RHuhBybdBOF7MfnICmSQ2SYjIBM3iRvkcMki9IRcnDTthyLz2Ld2fTzPjTQK+Mdg8y5nkZfFO+se9LQr3/09xZr+5GcaSufeAfAww60mAPx+q8u/bAr8rFCLrx7s+vqEkw8qb+p26n11Aruq6m1iJH6PbWGv1VIY25mkNE8PkaQhxfLIF7DZXx80HD/A3l2jLclYs061xNpWCfoB6WHJTjbH0mV35Q/lRXlC+W8cndbl9t2SfhU+Fb4UfhO+F74GWThknBZ+Em4InwjXIyd1ePnY/Psg3pb1TJNu15TMKWMtFt6ScpKL0ivSMXIn9QtDUlj0h7U7N48t3i8eC0GnMC91dX2sTivgloDTgUVeEGHLTizbf5Da9JLhkhh29QOs1luMcScmBXTIIt7xRFxSBxnuJWfuAd1I7jntkyd/pgKaIwVr3MgmDo2q8x6IdB5QH162mcX7ajtnHGN2bov71OU1+U0fqqoXLD0wX5ZM005UHmySz3qLtDqILDvIL+iH6jB9y2x83ok898GOPQX3lk3Itl0A+BrD6D7tUjWh3fis58BXDigN9yF8M5PJH4B8Gr79/F/XRm8m241mw/wvur4BGDj42bzn+Vmc+NL9L8GcMn8F1kAcXgSteGGAAABWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpMwidZAAAEkElEQVR4Ae3QMQEAAADCoPVP7WsIiEBhwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDDwAwMBPAABGrpAUwAAAABJRU5ErkJggg==",a.style.visibility="visible",a.src=h,""})},this._storeTile=function(a,b,c,d){a=a.split("?")[0] +var e=b?b+"?"+a:a,f=new XMLHttpRequest +f.open("GET",e,!0),f.overrideMimeType("text/plain; charset=x-user-defined"),f.onload=function(){if(200===f.status&&""!==f.responseText){var b=O.esri.Tiles.Base64Utils.wordToBase64(O.esri.Tiles.Base64Utils.stringToWord(this.responseText)),g={url:a,img:b} +c.store(g,d)}else d(!1,f.status+" "+f.statusText+": "+f.response+" when downloading "+e)},f.onerror=function(a){d(!1,a)},f.send(null)},this._createCellsForOffline=function(a,b,c,d,e){for(var f=new O.esri.Tiles.TilingScheme(a),g=[],h=b;c>=h;h++){var i=f.getAllCellIdsInExtent(d,h) +if(i.forEach(function(a){g.push({level:h,row:a[1],col:a[0]})}),g.length>5e3&&h!==c)break}e(g)},this._saveToFile=function(a,b,c){var d=[] +d.push("url,img"),b.getAllTiles(function(b,e,f){if("end"===f){var g=new Blob([d.join("\r\n")],{type:"text/plain;charset=utf-8"}),h=O.esri.Tiles.saveAs(g,a) +if(h.readyState===h.DONE)return h.error?c(!1,"Error saving file "+a):c(!0,"Saved "+(d.length-1)+" tiles ("+Math.floor(g.size/1024/1024*100)/100+" Mb) into "+a) +h.onerror=function(){c(!1,"Error saving file "+a)},h.onwriteend=function(){c(!0,"Saved "+(d.length-1)+" tiles ("+Math.floor(g.size/1024/1024*100)/100+" Mb) into "+a)}}else d.push(b+","+e)})},this._estimateTileSize=function(a,b,c,d){if(b){var e,f=window.localStorage.offline_id_manager +if(void 0===f||""===f)e="" +else{var g=JSON.parse(f) +g.credentials.forEach(function(a){-1!==b.indexOf(a.server)&&(e="?token="+a.token)})}var h=c?c+"?"+b+e:b+e +a.get(h,{handleAs:"text/plain; charset=x-user-defined",headers:{"X-Requested-With":""},timeout:2e3}).then(function(a){var b=O.esri.Tiles.Base64Utils.wordToBase64(O.esri.Tiles.Base64Utils.stringToWord(a)) +d(b.length+h.length,null)},function(a){d(null,a)})}else d(NaN)},this._loadFromFile=function(a,b,c){if(window.File&&window.FileReader&&window.FileList&&window.Blob){var d=new FileReader +d.onload=function(d){var e,f,g=d.target.result,h=g.split("\r\n"),i=0 +if("url,img"!==h[0])return c(!1,"File "+a.name+" doesn't contain tiles that can be loaded") +for(var j=1;j=c;c++)for(d=i;j>=d;d++)k.push([c,d]) +return k}} diff --git a/dist/offline-tiles-advanced-src.js b/dist/offline-tiles-advanced-src.js index 1d7e17ee..b4b96bcb 100644 --- a/dist/offline-tiles-advanced-src.js +++ b/dist/offline-tiles-advanced-src.js @@ -1,4 +1,4 @@ -/*! esri-offline-maps - v2.16.0 - 2015-10-29 +/*! esri-offline-maps - v3.0.0 - 2015-11-23 * Copyright (c) 2015 Environmental Systems Research Institute, Inc. * Apache License*/ define([ @@ -15,7 +15,7 @@ define([ ], function(query, request, declare,LOD,Point,Extent,TileInfo,SpatialReference,Polygon,TiledMapServerLayer) { "use strict"; - return declare("O.esri.Tiles.OfflineTileEnablerLayer",[TiledMapServerLayer],{ + return declare("O.esri.Tiles.OfflineTilesAdvanced",[TiledMapServerLayer],{ tileInfo: null, _imageType: "", @@ -898,8 +898,8 @@ O.esri.Tiles.saveAs = /** - * This library contains common core code between offlineTilesEnabler.js - * and OfflineTilesEnablerLayer.js + * This library contains common core code between OfflineTilesBasic.js + * and OfflineTilesAdvanced.js */ O.esri.Tiles.TilesCore = function(){ diff --git a/dist/offline-tiles-basic-min.js b/dist/offline-tiles-basic-min.js index 3d28da50..97334721 100644 --- a/dist/offline-tiles-basic-min.js +++ b/dist/offline-tiles-basic-min.js @@ -1,5 +1,81 @@ -/*! esri-offline-maps - v2.16.0 - 2015-10-29 +/*! esri-offline-maps - v3.0.0 - 2015-11-23 * Copyright (c) 2015 Environmental Systems Research Institute, Inc. * Apache License*/ -define(["dojo/query","dojo/request","esri/geometry/Polygon","dojo/_base/declare"],function(a,b,c,d){"use strict";return d("O.esri.Tiles.OfflineTilesEnabler",[],{getBasemapLayer:function(a){var b=a.layerIds[0];return a.getLayer(b)},extend:function(c,d,e,f){c._tilesCore=new O.esri.Tiles.TilesCore,c._lastTileUrl="",c._imageType="",c._minZoom=null,c._maxZoom=null,void 0===f||null===f?(c.DB_NAME="offline_tile_store",c.DB_OBJECTSTORE_NAME="tilepath"):(c.DB_NAME=f.dbName,c.DB_OBJECTSTORE_NAME=f.objectStoreName),c._getTileUrl=c.getTileUrl;var g=!0;return"undefined"!=typeof e&&(g=e),c.showBlankTiles=!0,c.offline={online:g,store:new O.esri.Tiles.TilesStore,proxyPath:null},c.offline.store.isSupported()?(c.offline.store.dbName=c.DB_NAME,c.offline.store.objectStoreName=c.DB_OBJECTSTORE_NAME,c.offline.store.init(function(b){b&&(c.resampling=!1,c.getTileUrl=function(b,d,e){var f=this._getTileUrl(b,d,e);if(this.offline.online)return""===c._imageType&&(c._imageType=this.tileInfo.format.toLowerCase()),c._lastTileUrl=f,f;f=f.split("?")[0];var g="void:/"+b+"/"+d+"/"+e,h=null;return c._tilesCore._getTiles(h,this._imageType,f,g,this.offline.store,a,c.showBlankTiles),g},d&&d(!0))}.bind(this)),c.getLevelEstimation=function(a,b,c){var d=new O.esri.Tiles.TilingScheme(this),e=d.getAllCellIdsInExtent(a,b),f={level:b,tileCount:e.length,sizeBytes:e.length*c};return f},c.prepareForOffline=function(a,b,d,e){c._tilesCore._createCellsForOffline(this,a,b,d,function(a){this._doNextTile(0,a,e)}.bind(this))},c.goOffline=function(){this.offline.online=!1},c.goOnline=function(){this.offline.online=!0,this.refresh()},c.isOnline=function(){return this.offline.online},c.deleteAllTiles=function(a){var b=this.offline.store;b.deleteAll(a)},c.getOfflineUsage=function(a){var b=this.offline.store;b.usedSpace(a)},c.getTilePolygons=function(a){c._tilesCore._getTilePolygons(this.offline.store,c.url,this,a)},c.saveToFile=function(a,b){c._tilesCore._saveToFile(a,this.offline.store,b)},c.loadFromFile=function(a,b){c._tilesCore._loadFromFile(a,this.offline.store,b)},c.getMaxZoom=function(a){null==this._maxZoom&&(this._maxZoom=c.tileInfo.lods[c.tileInfo.lods.length-1].level),a(this._maxZoom)},c.getMinZoom=function(a){null==this._minZoom&&(this._minZoom=c.tileInfo.lods[0].level),a(this._minZoom)},c.getMinMaxLOD=function(a,b){var d={},e=c.getMap(),f=e.getLevel()-Math.abs(a),g=e.getLevel()+b;return null!=this._maxZoom&&null!=this._minZoom?(d.max=Math.min(this._maxZoom,g),d.min=Math.max(this._minZoom,f)):(c.getMinZoom(function(a){d.min=Math.max(a,f)}),c.getMaxZoom(function(a){d.max=Math.min(a,g)})),d},c.estimateTileSize=function(a){c._tilesCore._estimateTileSize(b,this._lastTileUrl,this.offline.proxyPath,a)},c.getExtentBuffer=function(a,b){return b.xmin-=a,b.ymin-=a,b.xmax+=a,b.ymax+=a,b},c.getTileUrlsByExtent=function(a,b){var d=new O.esri.Tiles.TilingScheme(c),e=d.getAllCellIdsInExtent(a,b),f=[];return e.forEach(function(a){f.push(c.url+"/"+b+"/"+a[1]+"/"+a[0])}.bind(this)),f},void(c._doNextTile=function(a,b,d){var e=b[a],f=this._getTileUrl(e.level,e.row,e.col);c._tilesCore._storeTile(f,this.offline.proxyPath,this.offline.store,function(c,f){c||(f={cell:e,msg:f});var g=d({countNow:a,countMax:b.length,cell:e,error:f,finishedDownloading:!1});g||a===b.length-1?d({finishedDownloading:!0,cancelRequested:g}):this._doNextTile(a+1,b,d)}.bind(this))})):d(!1,"indexedDB not supported")}})}),"undefined"!=typeof O?O.esri.Tiles={}:(O={},O.esri={Tiles:{}}),O.esri.Tiles.Base64Utils={},O.esri.Tiles.Base64Utils.outputTypes={Base64:0,Hex:1,String:2,Raw:3},O.esri.Tiles.Base64Utils.addWords=function(a,b){var c=(65535&a)+(65535&b),d=(a>>16)+(b>>16)+(c>>16);return d<<16|65535&c},O.esri.Tiles.Base64Utils.stringToWord=function(a){for(var b=8,c=(1<e;e+=b)d[e>>5]|=(a.charCodeAt(e/b)&c)<e;e+=b)d.push(String.fromCharCode(a[e>>5]>>>e%32&c));return d.join("")},O.esri.Tiles.Base64Utils.wordToHex=function(a){for(var b="0123456789abcdef",c=[],d=0,e=4*a.length;e>d;d++)c.push(b.charAt(a[d>>2]>>d%4*8+4&15)+b.charAt(a[d>>2]>>d%4*8&15));return c.join("")},O.esri.Tiles.Base64Utils.wordToBase64=function(a){for(var b="=",c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",d=[],e=0,f=4*a.length;f>e;e+=3)for(var g=(a[e>>2]>>8*(e%4)&255)<<16|(a[e+1>>2]>>8*((e+1)%4)&255)<<8|a[e+2>>2]>>8*((e+2)%4)&255,h=0;4>h;h++)8*e+6*h>32*a.length?d.push(b):d.push(c.charAt(g>>6*(3-h)&63));return d.join("")},/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ -O.esri.Tiles.saveAs=function(a){"use strict";var b=a.document,c=function(){return a.URL||a.webkitURL||a},d=a.URL||a.webkitURL||a,e=b.createElementNS("http://www.w3.org/1999/xhtml","a"),f=!a.externalHost&&"download"in e,g=a.webkitRequestFileSystem,h=a.requestFileSystem||g||a.mozRequestFileSystem,i=function(b){(a.setImmediate||a.setTimeout)(function(){throw b},0)},j="application/octet-stream",k=0,l=[],m=function(){for(var a=l.length;a--;){var b=l[a];"string"==typeof b?d.revokeObjectURL(b):b.remove()}l.length=0},n=function(a,b,c){b=[].concat(b);for(var d=b.length;d--;){var e=a["on"+b[d]];if("function"==typeof e)try{e.call(a,c||a)}catch(f){i(f)}}},o=function(d,i){var m,o,p,q=this,r=d.type,s=!1,t=function(){var a=c().createObjectURL(d);return l.push(a),a},u=function(){n(q,"writestart progress write writeend".split(" "))},v=function(){(s||!m)&&(m=t(d)),o?o.location.href=m:window.open(m,"_blank"),q.readyState=q.DONE,u()},w=function(a){return function(){return q.readyState!==q.DONE?a.apply(this,arguments):void 0}},x={create:!0,exclusive:!1};if(q.readyState=q.INIT,i||(i="download"),f){m=t(d),b=a.document,e=b.createElementNS("http://www.w3.org/1999/xhtml","a"),e.href=m,e.download=i;var y=b.createEvent("MouseEvents");return y.initMouseEvent("click",!0,!1,a,0,0,0,0,0,!1,!1,!1,!1,0,null),e.dispatchEvent(y),q.readyState=q.DONE,void u()}return a.chrome&&r&&r!==j&&(p=d.slice||d.webkitSlice,d=p.call(d,0,d.size,j),s=!0),g&&"download"!==i&&(i+=".download"),(r===j||g)&&(o=a),h?(k+=d.size,void h(a.TEMPORARY,k,w(function(a){a.root.getDirectory("saved",x,w(function(a){var b=function(){a.getFile(i,x,w(function(a){a.createWriter(w(function(b){b.onwriteend=function(b){o.location.href=a.toURL(),l.push(a),q.readyState=q.DONE,n(q,"writeend",b)},b.onerror=function(){var a=b.error;a.code!==a.ABORT_ERR&&v()},"writestart progress write abort".split(" ").forEach(function(a){b["on"+a]=q["on"+a]}),b.write(d),q.abort=function(){b.abort(),q.readyState=q.DONE},q.readyState=q.WRITING}),v)}),v)};a.getFile(i,{create:!1},w(function(a){a.remove(),b()}),w(function(a){a.code===a.NOT_FOUND_ERR?b():v()}))}),v)}),v)):void v()},p=o.prototype,q=function(a,b){return new o(a,b)};return p.abort=function(){var a=this;a.readyState=a.DONE,n(a,"abort")},p.readyState=p.INIT=0,p.WRITING=1,p.DONE=2,p.error=p.onwritestart=p.onprogress=p.onwrite=p.onabort=p.onerror=p.onwriteend=null,a.addEventListener("unload",m,!1),q}(this.self||this.window||this.content),O.esri.Tiles.TilesCore=function(){this._getTiles=function(a,b,c,d,e,f,g){e.retrieve(c,function(c,e){a=f("img[src="+d+"]")[0];var h;return c?(a.style.borderColor="blue",h="data:image/"+b+";base64,"+e.img):g?(a.style.borderColor="green",h="data:image/png;base64,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pmk0TROPj48Hn3l4eIimaSJN06O3A4NJwDMxm82ibdtXo4D5fB6r1Sp+//4dz8/Pw5H+6ekpdrtdJEkS8/n8S/9f713ie3vaceo9x557QAB451Sgfyin34HKshweunk5HzAej2MymXz5+f9nbjJyI9L39Wu5XP55+XQZ39uxR4Z3u90wSXjqEV0wAjhjx47oaZq63Me/ZhIQBAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAAbAJQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAvqe/BwCeKjUweoA8pQAAAABJRU5ErkJggg=="):h="data:image/png;base64,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AwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDDwAwMBPAABGrpAUwAAAABJRU5ErkJggg==",a.style.visibility="visible",a.src=h,""})},this._storeTile=function(a,b,c,d){a=a.split("?")[0];var e=b?b+"?"+a:a,f=new XMLHttpRequest;f.open("GET",e,!0),f.overrideMimeType("text/plain; charset=x-user-defined"),f.onload=function(){if(200===f.status&&""!==f.responseText){var b=O.esri.Tiles.Base64Utils.wordToBase64(O.esri.Tiles.Base64Utils.stringToWord(this.responseText)),g={url:a,img:b};c.store(g,d)}else d(!1,f.status+" "+f.statusText+": "+f.response+" when downloading "+e)},f.onerror=function(a){d(!1,a)},f.send(null)},this._createCellsForOffline=function(a,b,c,d,e){for(var f=new O.esri.Tiles.TilingScheme(a),g=[],h=b;c>=h;h++){var i=f.getAllCellIdsInExtent(d,h);if(i.forEach(function(a){g.push({level:h,row:a[1],col:a[0]})}),g.length>5e3&&h!==c)break}e(g)},this._saveToFile=function(a,b,c){var d=[];d.push("url,img"),b.getAllTiles(function(b,e,f){if("end"===f){var g=new Blob([d.join("\r\n")],{type:"text/plain;charset=utf-8"}),h=O.esri.Tiles.saveAs(g,a);if(h.readyState===h.DONE)return h.error?c(!1,"Error saving file "+a):c(!0,"Saved "+(d.length-1)+" tiles ("+Math.floor(g.size/1024/1024*100)/100+" Mb) into "+a);h.onerror=function(){c(!1,"Error saving file "+a)},h.onwriteend=function(){c(!0,"Saved "+(d.length-1)+" tiles ("+Math.floor(g.size/1024/1024*100)/100+" Mb) into "+a)}}else d.push(b+","+e)})},this._estimateTileSize=function(a,b,c,d){if(b){var e,f=window.localStorage.offline_id_manager;if(void 0===f||""===f)e="";else{var g=JSON.parse(f);g.credentials.forEach(function(a){-1!==b.indexOf(a.server)&&(e="?token="+a.token)})}var h=c?c+"?"+b+e:b+e;a.get(h,{handleAs:"text/plain; charset=x-user-defined",headers:{"X-Requested-With":""},timeout:2e3}).then(function(a){var b=O.esri.Tiles.Base64Utils.wordToBase64(O.esri.Tiles.Base64Utils.stringToWord(a));d(b.length+h.length,null)},function(a){d(null,a)})}else d(NaN)},this._loadFromFile=function(a,b,c){if(window.File&&window.FileReader&&window.FileList&&window.Blob){var d=new FileReader;d.onload=function(d){var e,f,g=d.target.result,h=g.split("\r\n"),i=0;if("url,img"!==h[0])return c(!1,"File "+a.name+" doesn't contain tiles that can be loaded");for(var j=1;j=c;c++)for(d=i;j>=d;d++)k.push([c,d]);return k}}; \ No newline at end of file +define(["dojo/query","dojo/request","esri/geometry/Polygon","dojo/_base/declare"],function(a,b,c,d){"use strict" +return d("O.esri.Tiles.OfflineTilesBasic",[],{getBasemapLayer:function(a){var b=a.layerIds[0] +return a.getLayer(b)},extend:function(c,d,e,f){c._tilesCore=new O.esri.Tiles.TilesCore,c._lastTileUrl="",c._imageType="",c._minZoom=null,c._maxZoom=null,void 0===f||null===f?(c.DB_NAME="offline_tile_store",c.DB_OBJECTSTORE_NAME="tilepath"):(c.DB_NAME=f.dbName,c.DB_OBJECTSTORE_NAME=f.objectStoreName),c._getTileUrl=c.getTileUrl +var g=!0 +return"undefined"!=typeof e&&(g=e),c.showBlankTiles=!0,c.offline={online:g,store:new O.esri.Tiles.TilesStore,proxyPath:null},c.offline.store.isSupported()?(c.offline.store.dbName=c.DB_NAME,c.offline.store.objectStoreName=c.DB_OBJECTSTORE_NAME,c.offline.store.init(function(b){b&&(c.resampling=!1,c.getTileUrl=function(b,d,e){var f=this._getTileUrl(b,d,e) +if(this.offline.online)return""===c._imageType&&(c._imageType=this.tileInfo.format.toLowerCase()),c._lastTileUrl=f,f +f=f.split("?")[0] +var g="void:/"+b+"/"+d+"/"+e,h=null +return c._tilesCore._getTiles(h,this._imageType,f,g,this.offline.store,a,c.showBlankTiles),g},d&&d(!0))}.bind(this)),c.getLevelEstimation=function(a,b,c){var d=new O.esri.Tiles.TilingScheme(this),e=d.getAllCellIdsInExtent(a,b),f={level:b,tileCount:e.length,sizeBytes:e.length*c} +return f},c.prepareForOffline=function(a,b,d,e){c._tilesCore._createCellsForOffline(this,a,b,d,function(a){this._doNextTile(0,a,e)}.bind(this))},c.goOffline=function(){this.offline.online=!1},c.goOnline=function(){this.offline.online=!0,this.refresh()},c.isOnline=function(){return this.offline.online},c.deleteAllTiles=function(a){var b=this.offline.store +b.deleteAll(a)},c.getOfflineUsage=function(a){var b=this.offline.store +b.usedSpace(a)},c.getTilePolygons=function(a){c._tilesCore._getTilePolygons(this.offline.store,c.url,this,a)},c.saveToFile=function(a,b){c._tilesCore._saveToFile(a,this.offline.store,b)},c.loadFromFile=function(a,b){c._tilesCore._loadFromFile(a,this.offline.store,b)},c.getMaxZoom=function(a){null==this._maxZoom&&(this._maxZoom=c.tileInfo.lods[c.tileInfo.lods.length-1].level),a(this._maxZoom)},c.getMinZoom=function(a){null==this._minZoom&&(this._minZoom=c.tileInfo.lods[0].level),a(this._minZoom)},c.getMinMaxLOD=function(a,b){var d={},e=c.getMap(),f=e.getLevel()-Math.abs(a),g=e.getLevel()+b +return null!=this._maxZoom&&null!=this._minZoom?(d.max=Math.min(this._maxZoom,g),d.min=Math.max(this._minZoom,f)):(c.getMinZoom(function(a){d.min=Math.max(a,f)}),c.getMaxZoom(function(a){d.max=Math.min(a,g)})),d},c.estimateTileSize=function(a){c._tilesCore._estimateTileSize(b,this._lastTileUrl,this.offline.proxyPath,a)},c.getExtentBuffer=function(a,b){return b.xmin-=a,b.ymin-=a,b.xmax+=a,b.ymax+=a,b},c.getTileUrlsByExtent=function(a,b){var d=new O.esri.Tiles.TilingScheme(c),e=d.getAllCellIdsInExtent(a,b),f=[] +return e.forEach(function(a){f.push(c.url+"/"+b+"/"+a[1]+"/"+a[0])}.bind(this)),f},void(c._doNextTile=function(a,b,d){var e=b[a],f=this._getTileUrl(e.level,e.row,e.col) +c._tilesCore._storeTile(f,this.offline.proxyPath,this.offline.store,function(c,f){c||(f={cell:e,msg:f}) +var g=d({countNow:a,countMax:b.length,cell:e,error:f,finishedDownloading:!1}) +g||a===b.length-1?d({finishedDownloading:!0,cancelRequested:g}):this._doNextTile(a+1,b,d)}.bind(this))})):d(!1,"indexedDB not supported")}})}),"undefined"!=typeof O?O.esri.Tiles={}:(O={},O.esri={Tiles:{}}),O.esri.Tiles.Base64Utils={},O.esri.Tiles.Base64Utils.outputTypes={Base64:0,Hex:1,String:2,Raw:3},O.esri.Tiles.Base64Utils.addWords=function(a,b){var c=(65535&a)+(65535&b),d=(a>>16)+(b>>16)+(c>>16) +return d<<16|65535&c},O.esri.Tiles.Base64Utils.stringToWord=function(a){for(var b=8,c=(1<e;e+=b)d[e>>5]|=(a.charCodeAt(e/b)&c)<e;e+=b)d.push(String.fromCharCode(a[e>>5]>>>e%32&c)) +return d.join("")},O.esri.Tiles.Base64Utils.wordToHex=function(a){for(var b="0123456789abcdef",c=[],d=0,e=4*a.length;e>d;d++)c.push(b.charAt(a[d>>2]>>d%4*8+4&15)+b.charAt(a[d>>2]>>d%4*8&15)) +return c.join("")},O.esri.Tiles.Base64Utils.wordToBase64=function(a){for(var b="=",c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",d=[],e=0,f=4*a.length;f>e;e+=3)for(var g=(a[e>>2]>>8*(e%4)&255)<<16|(a[e+1>>2]>>8*((e+1)%4)&255)<<8|a[e+2>>2]>>8*((e+2)%4)&255,h=0;4>h;h++)8*e+6*h>32*a.length?d.push(b):d.push(c.charAt(g>>6*(3-h)&63)) +return d.join("")},/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ +O.esri.Tiles.saveAs=function(a){"use strict" +var b=a.document,c=function(){return a.URL||a.webkitURL||a},d=a.URL||a.webkitURL||a,e=b.createElementNS("http://www.w3.org/1999/xhtml","a"),f=!a.externalHost&&"download"in e,g=a.webkitRequestFileSystem,h=a.requestFileSystem||g||a.mozRequestFileSystem,i=function(b){(a.setImmediate||a.setTimeout)(function(){throw b},0)},j="application/octet-stream",k=0,l=[],m=function(){for(var a=l.length;a--;){var b=l[a] +"string"==typeof b?d.revokeObjectURL(b):b.remove()}l.length=0},n=function(a,b,c){b=[].concat(b) +for(var d=b.length;d--;){var e=a["on"+b[d]] +if("function"==typeof e)try{e.call(a,c||a)}catch(f){i(f)}}},o=function(d,i){var m,o,p,q=this,r=d.type,s=!1,t=function(){var a=c().createObjectURL(d) +return l.push(a),a},u=function(){n(q,"writestart progress write writeend".split(" "))},v=function(){(s||!m)&&(m=t(d)),o?o.location.href=m:window.open(m,"_blank"),q.readyState=q.DONE,u()},w=function(a){return function(){return q.readyState!==q.DONE?a.apply(this,arguments):void 0}},x={create:!0,exclusive:!1} +if(q.readyState=q.INIT,i||(i="download"),f){m=t(d),b=a.document,e=b.createElementNS("http://www.w3.org/1999/xhtml","a"),e.href=m,e.download=i +var y=b.createEvent("MouseEvents") +return y.initMouseEvent("click",!0,!1,a,0,0,0,0,0,!1,!1,!1,!1,0,null),e.dispatchEvent(y),q.readyState=q.DONE,void u()}return a.chrome&&r&&r!==j&&(p=d.slice||d.webkitSlice,d=p.call(d,0,d.size,j),s=!0),g&&"download"!==i&&(i+=".download"),(r===j||g)&&(o=a),h?(k+=d.size,void h(a.TEMPORARY,k,w(function(a){a.root.getDirectory("saved",x,w(function(a){var b=function(){a.getFile(i,x,w(function(a){a.createWriter(w(function(b){b.onwriteend=function(b){o.location.href=a.toURL(),l.push(a),q.readyState=q.DONE,n(q,"writeend",b)},b.onerror=function(){var a=b.error +a.code!==a.ABORT_ERR&&v()},"writestart progress write abort".split(" ").forEach(function(a){b["on"+a]=q["on"+a]}),b.write(d),q.abort=function(){b.abort(),q.readyState=q.DONE},q.readyState=q.WRITING}),v)}),v)} +a.getFile(i,{create:!1},w(function(a){a.remove(),b()}),w(function(a){a.code===a.NOT_FOUND_ERR?b():v()}))}),v)}),v)):void v()},p=o.prototype,q=function(a,b){return new o(a,b)} +return p.abort=function(){var a=this +a.readyState=a.DONE,n(a,"abort")},p.readyState=p.INIT=0,p.WRITING=1,p.DONE=2,p.error=p.onwritestart=p.onprogress=p.onwrite=p.onabort=p.onerror=p.onwriteend=null,a.addEventListener("unload",m,!1),q}(this.self||this.window||this.content),O.esri.Tiles.TilesCore=function(){this._getTiles=function(a,b,c,d,e,f,g){e.retrieve(c,function(c,e){a=f("img[src="+d+"]")[0] +var h +return c?(a.style.borderColor="blue",h="data:image/"+b+";base64,"+e.img):g?(a.style.borderColor="green",h="data:image/png;base64,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pmk0TROPj48Hn3l4eIimaSJN06O3A4NJwDMxm82ibdtXo4D5fB6r1Sp+//4dz8/Pw5H+6ekpdrtdJEkS8/n8S/9f713ie3vaceo9x557QAB451Sgfyin34HKshweunk5HzAej2MymXz5+f9nbjJyI9L39Wu5XP55+XQZ39uxR4Z3u90wSXjqEV0wAjhjx47oaZq63Me/ZhIQBAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAAbAJQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAvqe/BwCeKjUweoA8pQAAAABJRU5ErkJggg=="):h="data:image/png;base64,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AwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDDwAwMBPAABGrpAUwAAAABJRU5ErkJggg==",a.style.visibility="visible",a.src=h,""})},this._storeTile=function(a,b,c,d){a=a.split("?")[0] +var e=b?b+"?"+a:a,f=new XMLHttpRequest +f.open("GET",e,!0),f.overrideMimeType("text/plain; charset=x-user-defined"),f.onload=function(){if(200===f.status&&""!==f.responseText){var b=O.esri.Tiles.Base64Utils.wordToBase64(O.esri.Tiles.Base64Utils.stringToWord(this.responseText)),g={url:a,img:b} +c.store(g,d)}else d(!1,f.status+" "+f.statusText+": "+f.response+" when downloading "+e)},f.onerror=function(a){d(!1,a)},f.send(null)},this._createCellsForOffline=function(a,b,c,d,e){for(var f=new O.esri.Tiles.TilingScheme(a),g=[],h=b;c>=h;h++){var i=f.getAllCellIdsInExtent(d,h) +if(i.forEach(function(a){g.push({level:h,row:a[1],col:a[0]})}),g.length>5e3&&h!==c)break}e(g)},this._saveToFile=function(a,b,c){var d=[] +d.push("url,img"),b.getAllTiles(function(b,e,f){if("end"===f){var g=new Blob([d.join("\r\n")],{type:"text/plain;charset=utf-8"}),h=O.esri.Tiles.saveAs(g,a) +if(h.readyState===h.DONE)return h.error?c(!1,"Error saving file "+a):c(!0,"Saved "+(d.length-1)+" tiles ("+Math.floor(g.size/1024/1024*100)/100+" Mb) into "+a) +h.onerror=function(){c(!1,"Error saving file "+a)},h.onwriteend=function(){c(!0,"Saved "+(d.length-1)+" tiles ("+Math.floor(g.size/1024/1024*100)/100+" Mb) into "+a)}}else d.push(b+","+e)})},this._estimateTileSize=function(a,b,c,d){if(b){var e,f=window.localStorage.offline_id_manager +if(void 0===f||""===f)e="" +else{var g=JSON.parse(f) +g.credentials.forEach(function(a){-1!==b.indexOf(a.server)&&(e="?token="+a.token)})}var h=c?c+"?"+b+e:b+e +a.get(h,{handleAs:"text/plain; charset=x-user-defined",headers:{"X-Requested-With":""},timeout:2e3}).then(function(a){var b=O.esri.Tiles.Base64Utils.wordToBase64(O.esri.Tiles.Base64Utils.stringToWord(a)) +d(b.length+h.length,null)},function(a){d(null,a)})}else d(NaN)},this._loadFromFile=function(a,b,c){if(window.File&&window.FileReader&&window.FileList&&window.Blob){var d=new FileReader +d.onload=function(d){var e,f,g=d.target.result,h=g.split("\r\n"),i=0 +if("url,img"!==h[0])return c(!1,"File "+a.name+" doesn't contain tiles that can be loaded") +for(var j=1;j=c;c++)for(d=i;j>=d;d++)k.push([c,d]) +return k}} diff --git a/dist/offline-tiles-basic-src.js b/dist/offline-tiles-basic-src.js index 43064592..23423f46 100644 --- a/dist/offline-tiles-basic-src.js +++ b/dist/offline-tiles-basic-src.js @@ -1,4 +1,4 @@ -/*! esri-offline-maps - v2.16.0 - 2015-10-29 +/*! esri-offline-maps - v3.0.0 - 2015-11-23 * Copyright (c) 2015 Environmental Systems Research Institute, Inc. * Apache License*/ define([ @@ -9,7 +9,7 @@ define([ ], function(query, request, Polygon,declare) { "use strict"; - return declare("O.esri.Tiles.OfflineTilesEnabler",[],{ + return declare("O.esri.Tiles.OfflineTilesBasic",[],{ /** * Utility method to get the basemap layer reference * @param map @@ -730,8 +730,8 @@ O.esri.Tiles.saveAs = /** - * This library contains common core code between offlineTilesEnabler.js - * and OfflineTilesEnablerLayer.js + * This library contains common core code between OfflineTilesBasic.js + * and OfflineTilesAdvanced.js */ O.esri.Tiles.TilesCore = function(){ diff --git a/dist/offline-tpk-min.js b/dist/offline-tpk-min.js index 8fa2951c..2f0159da 100644 --- a/dist/offline-tpk-min.js +++ b/dist/offline-tpk-min.js @@ -1,5 +1,342 @@ -/*! esri-offline-maps - v2.16.0 - 2015-10-29 +/*! esri-offline-maps - v3.0.0 - 2015-11-23 * Copyright (c) 2015 Environmental Systems Research Institute, Inc. * Apache License*/ -define(["dojo/_base/declare","esri/geometry/Extent","dojo/query","esri/SpatialReference","esri/layers/TileInfo","esri/layers/TiledMapServiceLayer","dojo/Deferred","dojo/promise/all","dojo/Evented"],function(a,b,c,d,e,f,g,h,i){return a("O.esri.TPK.TPKLayer",[f,i],{map:null,store:null,MAX_DB_SIZE:75,TILE_PATH:"",RECENTER_DELAY:350,PARSING_ERROR:"parsingError",DB_INIT_ERROR:"dbInitError",DB_FULL_ERROR:"dbFullError",NO_SUPPORT_ERROR:"libNotSupportedError",PROGRESS_START:"start",PROGRESS_END:"end",WINDOW_VALIDATED:"windowValidated",DB_VALIDATED:"dbValidated",DATABASE_ERROR_EVENT:"databaseErrorEvent",VALIDATION_EVENT:"validationEvent",PROGRESS_EVENT:"progress",_maxDBSize:75,_isDBWriteable:!0,_isDBValid:!1,_autoCenter:null,_fileEntriesLength:0,_inMemTilesObject:null,_inMemTilesObjectLength:0,_zeroLengthFileCounter:0,constructor:function(){this._self=this,this._inMemTilesIndex=[],this._inMemTilesObject={},this.store=new O.esri.Tiles.TilesStore,this._validate()},extend:function(a){this._fileEntriesLength=a.length,this.emit(this.PROGRESS_EVENT,this.PROGRESS_START),this._parseInMemFiles(a,function(){this._parseConfCdi(function(a){this.initialExtent=this.fullExtent=a,this._parseConfXml(function(a){this.tileInfo=new e(a),this.spatialReference=new d({wkid:this.tileInfo.spatialReference.wkid}),this.loaded=!0,this.onLoad(this),this.emit(this.PROGRESS_EVENT,this.PROGRESS_END)}.bind(this._self))}.bind(this._self))}.bind(this._self))},getTileUrl:function(a,b,d){this.emit(this.PROGRESS_EVENT,this.PROGRESS_START);var e=this._self.TILE_PATH+"_alllayers",f=this._getCacheFilePath(e,a,b,d);if(this._inMemTilesObject!={}){var g="void:/"+a+"/"+b+"/"+d;return null==this.map&&(this.map=this.getMap()),null==this._autoCenter&&(this._autoCenter=new O.esri.TPK.autoCenterMap(this.map,this.RECENTER_DELAY),this._autoCenter.init()),this._getInMemTiles(f,e,a,b,d,g,function(a,b,d){var e=c("img[src="+b+"]")[0];"undefined"==typeof e&&(e=new Image);var f;if(a){var g="data:image/png;base64,";switch(this.tileInfo.format){case"JPEG":f="data:image/jpg;base64,"+a;break;case"PNG":f=g+a;break;case"PNG8":f=g+a;break;case"PNG24":f=g+a;break;case"PNG32":f=g+a;break;default:f="data:image/jpg;base64,"+a}e.style.borderColor="blue"}else e.style.borderColor="green",f="data:image/png;base64,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pmk0TROPj48Hn3l4eIimaSJN06O3A4NJwDMxm82ibdtXo4D5fB6r1Sp+//4dz8/Pw5H+6ekpdrtdJEkS8/n8S/9f713ie3vaceo9x557QAB451Sgfyin34HKshweunk5HzAej2MymXz5+f9nbjJyI9L39Wu5XP55+XQZ39uxR4Z3u90wSXjqEV0wAjhjx47oaZq63Me/ZhIQBAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAAbAJQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAvqe/BwCeKjUweoA8pQAAAABJRU5ErkJggg==";return e.style.visibility="visible",e.src=f,this.emit(this.PROGRESS_EVENT,this.PROGRESS_END),""}.bind(this._self)),g}},setMaxDBSize:function(a){var b=/^\d+$/;b.test(a)&&a<=this.MAX_DB_SIZE&&(this._maxDBSize=a)},getDBSize:function(a){this.store.usedSpace(function(b,c){a(b,c)}.bind(this))},setDBWriteable:function(a){this._isDBWriteable=a},isDBValid:function(){return this._validate(),this._isDBValid},loadFromURL:function(a,b){this.isDBValid()?this.store.store(a,function(a,c){a?b(!0,""):b(!1,c)}):b(!1,"not supported")},_validate:function(){window.File||window.FileReader||window.Blob||window.btoa||window.DataView?this.emit(this.VALIDATION_EVENT,{msg:this.WINDOW_VALIDATED,err:null}):this.emit(this.VALIDATION_EVENT,{msg:this.NO_SUPPORT_ERROR,err:null}),this.store.isSupported()?this.store.init(function(a){a===!1?this.emit(this.DATABASE_ERROR_EVENT,{msg:this.DB_INIT_ERROR,err:null}):this.store.usedSpace(function(a,b){var c=this._bytes2MBs(a.sizeBytes);c>this.MAX_DB_SIZE&&this.emit(this.DATABASE_ERROR_EVENT,{msg:this.DB_FULL_ERROR,err:b}),this.emit(this.VALIDATION_EVENT,{msg:this.DB_VALIDATED,err:null}),this._isDBValid=!0}.bind(this))}.bind(this)):this.emit(this.VALIDATION_EVENT,{msg:this.NO_SUPPORT_ERROR,err:null})},_parseInMemFiles:function(a,b){var c=this._fileEntriesLength;this._zeroLengthFileCounter=0;for(var d=[],e=0;c>e;e++){var f=new g,i=a[e].filename.toLocaleUpperCase(),j=i.indexOf("_ALLLAYERS",0);-1!=j&&(this.TILE_PATH=i.slice(0,j)),0===a[e].compressedSize&&this._zeroLengthFileCounter++;var k=i.indexOf("CONF.CDI",0),l=i.indexOf("CONF.XML",0),m=i.indexOf("BUNDLE",0),n=i.indexOf("BUNDLX",0);-1!=k||-1!=l?this._unzipConfFiles(a,e,f,function(a,b){a.resolve(b)}):-1!=m||-1!=n?this._unzipTileFiles(a,e,f,function(a,b){a.resolve(b)}):f.resolve(e),d.push(f)}h(d).then(function(a){b&&b(a)})},ObjectSize:function(a){var b,c=0;for(b in a)a.hasOwnProperty(b)&&c++;return c},_unzipConfFiles:function(a,b,c,d){a[b].getData(new O.esri.zip.TextWriter(b),function(b){this._inMemTilesIndex.push("blank");var e=a[b.token].filename.toLocaleUpperCase();this._inMemTilesObject[e]=b.string;var f=this.ObjectSize(this._inMemTilesObject);f>0&&d(c,b.token)}.bind(this))},_unzipTileFiles:function(a,b,c,d){var e=this;a[b].getData(new O.esri.zip.BlobWriter(b),function(b){if(0!==b.size){var f=new FileReader;f.token=b.token,f.onerror=function(a){e.emit(e.PARSING_ERROR,{msg:"Error parsing file: ",err:a.target.error})},f.onloadend=function(g){if(void 0!==f.token){e._inMemTilesIndex.push("blank");var h=a[f.token].filename.toLocaleUpperCase();e._inMemTilesObject[h]=f.result;var i=e.ObjectSize(e._inMemTilesObject);i>0&&d(c,b.token)}},f.readAsArrayBuffer(b)}})},_parseConfCdi:function(a){var c=this._inMemTilesObject[this.TILE_PATH+"CONF.CDI"],e=new O.esri.TPK.X2JS,f=e.xml_str2json(c),g=f.EnvelopeN,h=parseFloat(g.XMin),i=parseFloat(g.YMin),j=parseFloat(g.XMax),k=parseFloat(g.YMax),l=parseInt(g.SpatialReference.WKID),m=new b(h,i,j,k,new d({wkid:l}));a(m)},_parseConfXml:function(a){var b=this._inMemTilesObject[this.TILE_PATH+"CONF.XML"],c=new O.esri.TPK.X2JS,d=c.xml_str2json(b),e=d.CacheInfo,f={};f.rows=parseInt(e.TileCacheInfo.TileRows),f.cols=parseInt(e.TileCacheInfo.TileCols),f.dpi=parseInt(e.TileCacheInfo.DPI),f.format=e.TileImageInfo.CacheTileFormat,f.compressionQuality=parseInt(e.TileImageInfo.CompressionQuality),f.origin={x:parseInt(e.TileCacheInfo.TileOrigin.X),y:parseInt(e.TileCacheInfo.TileOrigin.Y)},f.spatialReference={wkid:parseInt(e.TileCacheInfo.SpatialReference.WKID)};for(var g=e.TileCacheInfo.LODInfos.LODInfo,h=[],i=0;im;m+=3)f=i[m]<<16|i[m+1]<<8|i[m+2],b=(16515072&f)>>18,c=(258048&f)>>12,d=(4032&f)>>6,e=63&f,g+=h[b]+h[c]+h[d]+h[e];return 1==k?(f=i[l],b=(252&f)>>2,c=(3&f)<<4,g+=h[b]+h[c]+"=="):2==k&&(f=i[l]<<8|i[l+1],b=(64512&f)>>10,c=(1008&f)>>4,d=(15&f)<<2,g+=h[b]+h[c]+h[d]+"="),g},_buffer2Base64:function(a,b,c){var d=new DataView(a,b),e=d.getInt32(0,!0),f=d.buffer.slice(b+4,b+4+e),g=this._base64ArrayBuffer(f);c(g)},_int2HexString:function(a){var b=a.toString(16).toUpperCase();return 1===b.length?"000"+b:2===b.length?"00"+b:3===b.length?"0"+b:b.substr(0,b.length)},_getOffset:function(a,b,c,d,e){var f=128*(c-e)+(b-d);return 16+5*f},_getCacheFilePath:function(a,b,c,d){var e=[];return e.push(a),e.push("/"),e.push("L"),e.push(10>b?"0"+b:b),e.push("/"),e.push("R"),e.push(this._int2HexString(c)),e.push("C"),e.push(this._int2HexString(d)),e.join("")},_bytes2MBs:function(a){return(a>>>20)+"."+(2046&a)}})}),"undefined"!=typeof O?O.esri.TPK={}:(O={},O.esri={TPK:{},Tiles:{}}),O.esri.Tiles.TilesStore=function(){this._db=null,this.dbName="offline_tile_store",this.objectStoreName="tilepath",this.isSupported=function(){return window.indexedDB||window.openDatabase?!0:!1},this.store=function(a,b){try{var c=this._db.transaction([this.objectStoreName],"readwrite");c.oncomplete=function(){b(!0)},c.onerror=function(a){b(!1,a.target.error.message)};var d=c.objectStore(this.objectStoreName),e=d.put(a);e.onsuccess=function(){}}catch(f){b(!1,f.stack)}},this.retrieve=function(a,b){if(null!==this._db){var c=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName),d=c.get(a);d.onsuccess=function(a){var c=a.target.result;void 0===c?b(!1,"not found"):b(!0,c)},d.onerror=function(a){b(!1,a)}}},this.deleteAll=function(a){if(null!==this._db){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear();b.onsuccess=function(){a(!0)},b.onerror=function(b){a(!1,b)}}else a(!1,null)},this["delete"]=function(a,b){if(null!==this._db){var c=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName)["delete"](a);c.onsuccess=function(){b(!0)},c.onerror=function(a){b(!1,a)}}else b(!1,null)},this.getAllTiles=function(a){if(null!==this._db){var b=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor();b.onsuccess=function(b){var c=b.target.result;if(c){var d=c.value.url,e=c.value.img;a(d,e,null),c["continue"]()}else a(null,null,"end")}.bind(this),b.onerror=function(b){a(null,null,b)}}else a(null,null,"no db")},this.usedSpace=function(a){if(null!==this._db){var b={sizeBytes:0,tileCount:0},c=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor();c.onsuccess=function(c){var d=c.target.result;if(d){var e=d.value,f=JSON.stringify(e);b.sizeBytes+=this._stringBytes(f),b.tileCount+=1,d["continue"]()}else a(b,null)}.bind(this),c.onerror=function(b){a(null,b)}}else a(null,null)},this._stringBytes=function(a){return a.length},this.init=function(a){var b=indexedDB.open(this.dbName,4);a=a||function(a){}.bind(this),b.onerror=function(b){a(!1,b.target.errorCode)}.bind(this),b.onupgradeneeded=function(a){var b=a.target.result;b.objectStoreNames.contains(this.objectStoreName)&&b.deleteObjectStore(this.objectStoreName),b.createObjectStore(this.objectStoreName,{keyPath:"url"})}.bind(this),b.onsuccess=function(b){this._db=b.target.result,a(!0)}.bind(this)}},function(a){function b(){var a=-1,b=this;b.append=function(c){var d,e=b.table;for(d=0;d>>8^e[255&(a^c[d])]},b.get=function(){return~a}}function c(a,b,c){return a.slice?a.slice(b,b+c):a.webkitSlice?a.webkitSlice(b,b+c):a.mozSlice?a.mozSlice(b,b+c):a.msSlice?a.msSlice(b,b+c):void 0}function d(a,b){var c,d;return c=new ArrayBuffer(a),d=new Uint8Array(c),b&&d.set(b,0),{buffer:c,array:d,view:new DataView(c)}}function e(){}function f(a){function b(b,c){var f=new Blob([a],{type:M});d=new h(f),d.init(function(){e.size=d.size,b()},c)}function c(a,b,c,e){d.readUint8Array(a,b,c,e)}var d,e=this;e.size=0,e.init=b,e.readUint8Array=c}function g(b){function c(a){for(var c=b.length;"="==b.charAt(c-1);)c--;f=b.indexOf(",")+1,g.size=Math.floor(.75*(c-f)),a()}function e(c,e,g){var h,i=d(e),j=4*Math.floor(c/3),k=4*Math.ceil((c+e)/3),l=a.atob(b.substring(j+f,k+f)),m=c-3*Math.floor(j/4);for(h=m;m+e>h;h++)i.array[h-m]=l.charCodeAt(h);g(i.array)}var f,g=this;g.size=0,g.init=c,g.readUint8Array=e}function h(a){function b(b){this.size=a.size,b()}function d(b,d,e,f){var g=new FileReader;g.onload=function(a){e(new Uint8Array(a.target.result))},g.onerror=f,g.readAsArrayBuffer(c(a,b,d))}var e=this;e.size=0,e.init=b,e.readUint8Array=d}function i(){}function j(a,b){function c(a){f=new Blob([],{type:M}),a()}function d(a,b){f=new Blob([f,A?a:a.buffer],{type:M}),b()}function e(c,d){var e=new FileReader;e.onload=function(b){var d={string:b.target.result,token:a};c(d)},e.onerror=d,e.readAsText(f,b)}var f,g=this;g.init=c,g.writeUint8Array=d,g.getData=e}function k(b){function c(a){g+="data:"+(b||"")+";base64,",a()}function d(b,c){var d,e=h.length,f=h;for(h="",d=0;d<3*Math.floor((e+b.length)/3)-e;d++)f+=String.fromCharCode(b[d]);for(;d2?g+=a.btoa(f):h=f,c()}function e(b){b(g+a.btoa(h))}var f=this,g="",h="";f.init=c,f.writeUint8Array=d,f.getData=e}function l(a,b){function c(a){f=new Blob([],{type:b}),a()}function d(c,d){f=new Blob([f,A?c:c.buffer],{type:b}),f.token=a,d()}function e(a){a(f)}var f,g=this;g.init=c,g.writeUint8Array=d,g.getData=e}function m(a,b,c,d,e,f,g,h,i,j){function k(){a.removeEventListener(N,l,!1),h(o)}function l(a){var b=a.data,d=b.data;b.onappend&&(o+=d.length,c.writeUint8Array(d,function(){f(!1,d),m()},j)),b.onflush&&(d?(o+=d.length,c.writeUint8Array(d,function(){f(!1,d),k()},j)):k()),b.progress&&g&&g(n+b.current,e)}function m(){n=p*J,e>n?b.readUint8Array(d+n,Math.min(J,e-n),function(b){a.postMessage({append:!0,data:b}),p++,g&&g(n,e),f(!0,b)},i):a.postMessage({flush:!0})}var n,o,p=0;o=0,a.addEventListener(N,l,!1),m()}function n(a,b,c,d,e,f,g,h,i,j){function k(){var o;l=m*J,e>l?b.readUint8Array(d+l,Math.min(J,e-l),function(b){var h=a.append(b,function(){g&&g(d+l,e)});n+=h.length,f(!0,b),c.writeUint8Array(h,function(){f(!1,h),m++,setTimeout(k,1)},j),g&&g(l,e)},i):(o=a.flush(),o?(n+=o.length,c.writeUint8Array(o,function(){f(!1,o),h(n)},j)):h(n))}var l,m=0,n=0;k()}function o(c,d,e,f,g,h,i,j,k){function l(a,b){g&&!a&&q.append(b)}function o(a){h(a,q.get())}var p,q=new b;return a.zip.useWebWorkers?(p=new Worker(a.zip.workerScriptsPath+K),m(p,c,d,e,f,l,i,o,j,k)):n(new a.zip.Inflater,c,d,e,f,l,i,o,j,k),p}function p(c,d,e,f,g,h,i){function j(a,b){a&&p.append(b)}function k(a){f(a,p.get())}function l(){o.removeEventListener(N,l,!1),m(o,c,d,0,c.size,j,g,k,h,i)}var o,p=new b;return a.zip.useWebWorkers?(o=new Worker(a.zip.workerScriptsPath+L),o.addEventListener(N,l,!1),o.postMessage({init:!0,level:e})):n(new a.zip.Deflater,c,d,0,c.size,j,g,k,h,i),o}function q(a,c,d,e,f,g,h,i,j){function k(){var b=l*J;e>b?a.readUint8Array(d+b,Math.min(J,e-b),function(a){f&&m.append(a),h&&h(b,e,a),c.writeUint8Array(a,function(){l++,k()},j)},i):g(e,m.get())}var l=0,m=new b;k()}function r(a){var b,c,d="",e=["Ç","ü","é","â","ä","à","å","ç","ê","ë","è","ï","î","ì","Ä","Å","É","æ","Æ","ô","ö","ò","û","ù","ÿ","Ö","Ü","ø","£","Ø","×","ƒ","á","í","ó","ú","ñ","Ñ","ª","º","¿","®","¬","½","¼","¡","«","»","_","_","_","¦","¦","Á","Â","À","©","¦","¦","+","+","¢","¥","+","+","-","-","+","-","+","ã","Ã","+","+","-","-","¦","-","+","¤","ð","Ð","Ê","Ë","È","i","Í","Î","Ï","+","+","_","_","¦","Ì","_","Ó","ß","Ô","Ò","õ","Õ","µ","þ","Þ","Ú","Û","Ù","ý","Ý","¯","´","­","±","_","¾","¶","§","÷","¸","°","¨","·","¹","³","²","_"," "];for(b=0;b127?e[c-128]:String.fromCharCode(c);return d}function s(a){return decodeURIComponent(escape(a))}function t(a){var b,c="";for(b=0;b>16,c=65535&a;try{return new Date(1980+((65024&b)>>9),((480&b)>>5)-1,31&b,(63488&c)>>11,(2016&c)>>5,2*(31&c),0)}catch(d){}}function v(a,b,c,d,e){return a.version=b.view.getUint16(c,!0),a.bitFlag=b.view.getUint16(c+2,!0),a.compressionMethod=b.view.getUint16(c+4,!0),a.lastModDateRaw=b.view.getUint32(c+6,!0),a.lastModDate=u(a.lastModDateRaw),1===(1&a.bitFlag)?void e(C):((d||8!=(8&a.bitFlag))&&(a.crc32=b.view.getUint32(c+10,!0),a.compressedSize=b.view.getUint32(c+14,!0),a.uncompressedSize=b.view.getUint32(c+18,!0)),4294967295===a.compressedSize||4294967295===a.uncompressedSize?void e(D):(a.filenameLength=b.view.getUint16(c+22,!0),void(a.extraFieldLength=b.view.getUint16(c+24,!0))))}function w(a,b){function c(){}function e(c,f){a.readUint8Array(a.size-c,c,function(a){var b=d(a.length,a).view;1347093766!=b.getUint32(0)?e(c+1,f):f(b)},function(){b(E)})}return c.prototype.getData=function(c,e,f,g){function h(a,b){m&&m.terminate(),m=null,a&&a(b)}function i(a){var b=d(4);return b.view.setUint32(0,a),n.crc32==b.view.getUint32(0)}function j(a,b){g&&!i(b)?k():c.getData(function(a){h(e,a)})}function k(){h(b,H)}function l(){h(b,G)}var m,n=this;a.readUint8Array(n.offset,30,function(e){var h,i=d(e.length,e);return 1347093252!=i.view.getUint32(0)?void b(B):(v(n,i,4,!1,b),h=n.offset+30+n.filenameLength+n.extraFieldLength,void c.init(function(){0===n.compressionMethod?q(a,c,h,n.compressedSize,g,j,f,k,l):m=o(a,c,h,n.compressedSize,g,j,f,k,l)},l))},k)},{getEntries:function(f){return a.size<22?void b(B):void e(22,function(e){var g,h;g=e.getUint32(16,!0),h=e.getUint16(8,!0),a.readUint8Array(g,a.size-g,function(a){var e,g,i,j,k=0,l=[],m=d(a.length,a);for(e=0;h>e;e++){if(g=new c,1347092738!=m.view.getUint32(k))return void b(B);v(g,m,k+6,!0,b),g.commentLength=m.view.getUint16(k+32,!0),g.directory=16==(16&m.view.getUint8(k+38)),g.offset=m.view.getUint32(k+42,!0),i=t(m.array.subarray(k+46,k+46+g.filenameLength)),g.filename=2048===(2048&g.bitFlag)?s(i):r(i),g.directory||"/"!=g.filename.charAt(g.filename.length-1)||(g.directory=!0),j=t(m.array.subarray(k+46+g.filenameLength+g.extraFieldLength,k+46+g.filenameLength+g.extraFieldLength+g.commentLength)),g.comment=2048===(2048&g.bitFlag)?s(j):r(j),l.push(g),k+=46+g.filenameLength+g.extraFieldLength+g.commentLength}f(l)},function(){b(E)})})},close:function(a){a&&a()}}}function x(a){return unescape(encodeURIComponent(a))}function y(a){var b,c=[];for(b=0;ba;a++){for(c=a,b=0;8>b;b++)1&c?c=c>>>1^3988292384:c>>>=1;d[a]=c}return d}(),f.prototype=new e,f.prototype.constructor=f,g.prototype=new e,g.prototype.constructor=g,h.prototype=new e,h.prototype.constructor=h,i.prototype.getData=function(a){a(this.data)},j.prototype=new i,j.prototype.constructor=j,k.prototype=new i,k.prototype.constructor=k,l.prototype=new i,l.prototype.constructor=l,a.zip={Reader:e,Writer:i,BlobReader:h,Data64URIReader:g,TextReader:f,BlobWriter:l,Data64URIWriter:k,TextWriter:j,createReader:function(a,b,c){a.init(function(){b(w(a,c))},c)},createWriter:function(a,b,c,d){a.init(function(){b(z(a,c,d))},c)},workerScriptsPath:"",useWebWorkers:!0}}(O.esri),O.esri.TPK.autoCenterMap=function(a,b){function c(a){var b="onorientationchange"in window,c=b?"orientationchange":"resize";window.addEventListener(c,e(function(){d()},a))}function d(){require(["esri/geometry/Point","esri/SpatialReference"],function(b,c){var d=i().split(","),e=a.spatialReference.wkid,f=null;4326==e?f=new b(d[1],d[0]):102100==e&&(f=new b(d[0],d[1],new c({wkid:e}))),a.centerAt(f)})}function e(a,b,c){var d;return function(){var e=this,f=arguments;clearTimeout(d),d=setTimeout(function(){d=null,c||a.apply(e,f)},b),c&&!d&&a.apply(e,f)}}function f(){a.on("pan-end",function(){var b=a.extent.getCenter();h(b.x,b.y,a.spatialReference.wkid)})}function g(){a.on("zoom-end",function(){var b=a.extent.getCenter();h(b.x,b.y,a.spatialReference.wkid),a.setZoom(a.getZoom())})}function h(a,b,c){localStorage.setItem("_centerPtX",a),localStorage.setItem("_centerPtY",b),localStorage.setItem("_spatialReference",c)}function i(){var a=null;try{a=localStorage.getItem("_centerPtX")+","+localStorage.getItem("_centerPtY")+","+localStorage.getItem("_spatialReference")}catch(b){}return a}this.init=function(){f(),g(),c(b);var d=a.extent.getCenter();h(d.x,d.y,a.spatialReference.wkid)}},O.esri.TPK.inflate=function(a){function b(){function a(a,b,c,d,j,k,l,n,p,r,s){var t,u,v,w,x,y,z,A,C,D,E,F,G,H,I;D=0,x=c;do e[a[b+D]]++,D++,x--;while(0!==x);if(e[0]==c)return l[0]=-1,n[0]=0,i;for(A=n[0],y=1;B>=y&&0===e[y];y++);for(z=y,y>A&&(A=y),x=B;0!==x&&0===e[x];x--);for(v=x,A>x&&(A=x),n[0]=A,H=1<y;y++,H<<=1)if((H-=e[y])<0)return m;if((H-=e[x])<0)return m;for(e[x]+=H,h[1]=y=0,D=1,G=2;0!==--x;)h[G]=y+=e[D],G++,D++;x=0,D=0;do 0!==(y=a[b+D])&&(s[h[y]++]=x),D++;while(++x=z;z++)for(t=e[z];0!==t--;){for(;z>F+A;){if(w++,F+=A,I=v-F,I=I>A?A:I,(u=1<<(y=z-F))>t+1&&(u-=t+1,G=z,I>y))for(;++yq)return m;g[w]=E=r[0],r[0]+=I,0!==w?(h[w]=x,f[0]=y,f[1]=A,y=x>>>F-A,f[2]=E-g[w-1]-y,p.set(f,3*(g[w-1]+y))):l[0]=E}for(f[1]=z-F,D>=c?f[0]=192:s[D]>>F;I>y;y+=u)p.set(f,3*(E+y));for(y=1<>>=1)x^=y;for(x^=y,C=(1<b;b++)d[b]=0;for(b=0;B+1>b;b++)e[b]=0;for(b=0;3>b;b++)f[b]=0;g.set(e.subarray(0,B),0),h.set(e.subarray(0,B+1),0)}var c,d,e,f,g,h,j=this;j.inflate_trees_bits=function(e,f,g,h,i){var j;return b(19),c[0]=0,j=a(e,0,19,19,null,null,g,f,h,c,d),j==m?i.msg="oversubscribed dynamic bit lengths tree":(j==o||0===f[0])&&(i.msg="incomplete dynamic bit lengths tree",j=m),j},j.inflate_trees_dynamic=function(e,f,g,h,j,k,l,p,q){var r;return b(288),c[0]=0,r=a(g,0,e,257,x,y,k,h,p,c,d),r!=i||0===h[0]?(r==m?q.msg="oversubscribed literal/length tree":r!=n&&(q.msg="incomplete literal/length tree",r=m),r):(b(288),r=a(g,e,f,0,z,A,l,j,p,c,d),r!=i||0===j[0]&&e>257?(r==m?q.msg="oversubscribed distance tree":r==o?(q.msg="incomplete distance tree",r=m):r!=n&&(q.msg="empty distance tree with lengths",r=m),r):i)}}function c(){function a(a,b,c,d,e,f,g,h){var k,l,n,o,q,r,s,t,u,v,w,x,y,z,A,B;s=h.next_in_index,t=h.avail_in,q=g.bitb,r=g.bitk,u=g.write,v=ur;)t--,q|=(255&h.read_byte(s++))<>=l[B+1],r-=l[B+1],0!==(16&o)){for(o&=15,y=l[B+2]+(q&p[o]),q>>=o,r-=o;15>r;)t--,q|=(255&h.read_byte(s++))<>=l[B+1],r-=l[B+1],0!==(16&o)){for(o&=15;o>r;)t--,q|=(255&h.read_byte(s++))<>=o,r-=o,v-=y,u>=z)A=u-z,u-A>0&&2>u-A?(g.window[u++]=g.window[A++],g.window[u++]=g.window[A++],y-=2):(g.window.set(g.window.subarray(A,A+2),u),u+=2,A+=2,y-=2);else{A=u-z;do A+=g.end;while(0>A);if(o=g.end-A,y>o){if(y-=o,u-A>0&&o>u-A){do g.window[u++]=g.window[A++];while(0!==--o)}else g.window.set(g.window.subarray(A,A+o),u),u+=o,A+=o,o=0;A=0}}if(u-A>0&&y>u-A){do g.window[u++]=g.window[A++];while(0!==--y)}else g.window.set(g.window.subarray(A,A+y),u),u+=y,A+=y,y=0;break}if(0!==(64&o))return h.msg="invalid distance code",y=h.avail_in-t,y=y>r>>3?r>>3:y,t+=y,s-=y,r-=y<<3,g.bitb=q,g.bitk=r,h.avail_in=t,h.total_in+=s-h.next_in_index,h.next_in_index=s,g.write=u,m;k+=l[B+2],k+=q&p[o],B=3*(n+k),o=l[B]}break}if(0!==(64&o))return 0!==(32&o)?(y=h.avail_in-t,y=y>r>>3?r>>3:y,t+=y,s-=y,r-=y<<3,g.bitb=q,g.bitk=r,h.avail_in=t,h.total_in+=s-h.next_in_index,h.next_in_index=s,g.write=u,j):(h.msg="invalid literal/length code",y=h.avail_in-t,y=y>r>>3?r>>3:y,t+=y,s-=y,r-=y<<3,g.bitb=q,g.bitk=r,h.avail_in=t,h.total_in+=s-h.next_in_index,h.next_in_index=s,g.write=u,m);if(k+=l[B+2],k+=q&p[o],B=3*(n+k),0===(o=l[B])){q>>=l[B+1],r-=l[B+1],g.window[u++]=l[B+2],v--;break}}else q>>=l[B+1],r-=l[B+1],g.window[u++]=l[B+2],v--}while(v>=258&&t>=10);return y=h.avail_in-t,y=y>r>>3?r>>3:y,t+=y,s-=y,r-=y<<3,g.bitb=q,g.bitk=r,h.avail_in=t,h.total_in+=s-h.next_in_index,h.next_in_index=s,g.write=u,i}var b,c,d,e,f=this,g=0,h=0,k=0,n=0,o=0,q=0,r=0,s=0,t=0,u=0;f.init=function(a,f,g,h,i,j){b=C,r=a,s=f,d=g,t=h,e=i,u=j,c=null},f.proc=function(f,v,w){var x,y,z,A,B,M,N,O=0,P=0,Q=0;for(Q=v.next_in_index,A=v.avail_in,O=f.bitb,P=f.bitk,B=f.write,M=B=258&&A>=10&&(f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,w=a(r,s,d,t,e,u,f,v),Q=v.next_in_index,A=v.avail_in,O=f.bitb,P=f.bitk,B=f.write,M=BP;){if(0===A)return f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,f.inflate_flush(v,w);w=i,A--,O|=(255&v.read_byte(Q++))<>>=c[y+1],P-=c[y+1],z=c[y],0===z){n=c[y+2],b=I;break}if(0!==(16&z)){o=15&z, -g=c[y+2],b=E;break}if(0===(64&z)){k=z,h=y/3+c[y+2];break}if(0!==(32&z)){b=J;break}return b=L,v.msg="invalid literal/length code",w=m,f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,f.inflate_flush(v,w);case E:for(x=o;x>P;){if(0===A)return f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,f.inflate_flush(v,w);w=i,A--,O|=(255&v.read_byte(Q++))<>=x,P-=x,k=s,c=e,h=u,b=F;case F:for(x=k;x>P;){if(0===A)return f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,f.inflate_flush(v,w);w=i,A--,O|=(255&v.read_byte(Q++))<>=c[y+1],P-=c[y+1],z=c[y],0!==(16&z)){o=15&z,q=c[y+2],b=G;break}if(0===(64&z)){k=z,h=y/3+c[y+2];break}return b=L,v.msg="invalid distance code",w=m,f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,f.inflate_flush(v,w);case G:for(x=o;x>P;){if(0===A)return f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,f.inflate_flush(v,w);w=i,A--,O|=(255&v.read_byte(Q++))<>=x,P-=x,b=H;case H:for(N=B-q;0>N;)N+=f.end;for(;0!==g;){if(0===M&&(B==f.end&&0!==f.read&&(B=0,M=B7&&(P-=8,A++,Q--),f.write=B,w=f.inflate_flush(v,w),B=f.write,M=Ba.avail_out&&(c=a.avail_out),0!==c&&b==o&&(b=i),a.avail_out-=c,a.total_out+=c,a.next_out.set(f.window.subarray(e,e+c),d),d+=c,e+=c,e==f.end&&(e=0,f.write==f.end&&(f.write=0),c=f.write-e,c>a.avail_out&&(c=a.avail_out),0!==c&&b==o&&(b=i),a.avail_out-=c,a.total_out+=c,a.next_out.set(f.window.subarray(e,e+c),d),d+=c,e+=c),a.next_out_index=d,f.read=e,b},f.proc=function(a,c){var d,o,q,w,y,z,A,B;for(w=a.next_in_index,y=a.avail_in,o=f.bitb,q=f.bitk,z=f.write,A=zq;){if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c);c=i,y--,o|=(255&a.read_byte(w++))<>>1){case 0:o>>>=3,q-=3,d=7&q,o>>>=d,q-=d,g=O;break;case 1:var C=[],D=[],E=[[]],F=[[]];b.inflate_trees_fixed(C,D,E,F),t.init(C[0],D[0],E[0],0,F[0],0),o>>>=3,q-=3,g=T;break;case 2:o>>>=3,q-=3,g=Q;break;case 3:return o>>>=3,q-=3,g=W,a.msg="invalid block type",c=m,f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c)}break;case O:for(;32>q;){if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c);c=i,y--,o|=(255&a.read_byte(w++))<>>16&65535)!=(65535&o))return g=W,a.msg="invalid stored block lengths",c=m,f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c);h=65535&o,o=q=0,g=0!==h?P:0!==u?U:N;break;case P:if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c);if(0===A&&(z==f.end&&0!==f.read&&(z=0,A=zy&&(d=y),d>A&&(d=A),f.window.set(a.read_buf(w,d),z),w+=d,y-=d,z+=d,A-=d,0!==(h-=d))break;g=0!==u?U:N;break;case Q:for(;14>q;){if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c);c=i,y--,o|=(255&a.read_byte(w++))<29||(d>>5&31)>29)return g=W,a.msg="too many length or distance symbols",c=m,f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c);if(d=258+(31&d)+(d>>5&31),!e||e.lengthB;B++)e[B]=0;o>>>=14,q-=14,n=0,g=R;case R:for(;4+(k>>>10)>n;){for(;3>q;){if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c);c=i,y--,o|=(255&a.read_byte(w++))<>>=3,q-=3}for(;19>n;)e[M[n++]]=0;if(r[0]=7,d=x.inflate_trees_bits(e,r,s,v,a),d!=i)return c=d,c==m&&(e=null,g=W),f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c);n=0,g=S;case S:for(;;){if(d=k,!(258+(31&d)+(d>>5&31)>n))break;var G,H;for(d=r[0];d>q;){if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c);c=i,y--,o|=(255&a.read_byte(w++))<H)o>>>=d,q-=d,e[n++]=H;else{for(B=18==H?7:H-14,G=18==H?11:3;d+B>q;){if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c);c=i,y--,o|=(255&a.read_byte(w++))<>>=d,q-=d,G+=o&p[B],o>>>=B,q-=B,B=n,d=k,B+G>258+(31&d)+(d>>5&31)||16==H&&1>B)return e=null,g=W,a.msg="invalid bit length repeat",c=m,f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c);H=16==H?e[B-1]:0;do e[B++]=H;while(0!==--G);n=B}}s[0]=-1;var I=[],J=[],K=[],L=[];if(I[0]=9,J[0]=6,d=k,d=x.inflate_trees_dynamic(257+(31&d),1+(d>>5&31),e,I,J,K,L,v,a),d!=i)return d==m&&(e=null,g=W),c=d,f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c);t.init(I[0],J[0],v,K[0],v,L[0]),g=T;case T:if(f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,(c=t.proc(f,a,c))!=j)return f.inflate_flush(a,c);if(c=i,t.free(a),w=a.next_in_index,y=a.avail_in,o=f.bitb,q=f.bitk,z=f.write,A=ze||e>15?(b.inflateEnd(c),l):(b.wbits=e,c.istate.blocks=new d(c,1<>4)+8>a.istate.wbits){a.istate.mode=ga,a.msg="invalid window size",a.istate.marker=5;break}a.istate.mode=$;case $:if(0===a.avail_in)return c;if(c=b,a.avail_in--,a.total_in++,d=255&a.read_byte(a.next_in_index++),((a.istate.method<<8)+d)%31!==0){a.istate.mode=ga,a.msg="incorrect header check",a.istate.marker=5;break}if(0===(d&X)){a.istate.mode=ea;break}a.istate.mode=_;case _:if(0===a.avail_in)return c;c=b,a.avail_in--,a.total_in++,a.istate.need=(255&a.read_byte(a.next_in_index++))<<24&4278190080,a.istate.mode=aa;case aa:if(0===a.avail_in)return c;c=b,a.avail_in--,a.total_in++,a.istate.need+=(255&a.read_byte(a.next_in_index++))<<16&16711680,a.istate.mode=ba;case ba:if(0===a.avail_in)return c;c=b,a.avail_in--,a.total_in++,a.istate.need+=(255&a.read_byte(a.next_in_index++))<<8&65280,a.istate.mode=ca;case ca:return 0===a.avail_in?c:(c=b,a.avail_in--,a.total_in++,a.istate.need+=255&a.read_byte(a.next_in_index++),a.istate.mode=da,k);case da:return a.istate.mode=ga,a.msg="need dictionary",a.istate.marker=0,l;case ea:if(c=a.istate.blocks.proc(a,c),c==m){a.istate.mode=ga,a.istate.marker=0;break}if(c==i&&(c=b),c!=j)return c;c=b,a.istate.blocks.reset(a,a.istate.was),a.istate.mode=fa;case fa:return j;case ga:return m;default:return l}},b.inflateSetDictionary=function(a,b,c){var d=0,e=c;return a&&a.istate&&a.istate.mode==da?(e>=1<e;)b.read_byte(d)==ha[e]?e++:e=0!==b.read_byte(d)?0:4-e,d++,c--;return b.total_in+=d-b.next_in_index,b.next_in_index=d,b.avail_in=c,b.istate.marker=e,4!=e?m:(f=b.total_in,g=b.total_out,a(b),b.total_in=f,b.total_out=g,b.istate.mode=ea,i)},b.inflateSyncPoint=function(a){return a&&a.istate&&a.istate.blocks?a.istate.blocks.sync_point():l}}function f(){}function g(){var a=this,b=new f,c=512,d=r,e=new Uint8Array(c),g=!1;b.inflateInit(),b.next_out=e,a.append=function(a,f){var h,k,l=[],m=0,n=0,p=0;if(0!==a.length){b.next_in_index=0,b.next_in=a,b.avail_in=a.length;do{if(b.next_out_index=0,b.avail_out=c,0!==b.avail_in||g||(b.next_in_index=0,g=!0),h=b.inflate(d),g&&h==o)return-1;if(h!=i&&h!=j)throw"inflating: "+b.msg;if((g||h==j)&&b.avail_in==a.length)return-1;b.next_out_index&&(b.next_out_index==c?l.push(new Uint8Array(e)):l.push(new Uint8Array(e.subarray(0,b.next_out_index)))),p+=b.next_out_index,f&&b.next_in_index>0&&b.next_in_index!=m&&(f(b.next_in_index),m=b.next_in_index)}while(b.avail_in>0||0===b.avail_out);return k=new Uint8Array(p),l.forEach(function(a){k.set(a,n),n+=a.length}),k}},a.flush=function(){b.inflateEnd()}}var h=15,i=0,j=1,k=2,l=-2,m=-3,n=-4,o=-5,p=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],q=1440,r=0,s=4,t=9,u=5,v=[96,7,256,0,8,80,0,8,16,84,8,115,82,7,31,0,8,112,0,8,48,0,9,192,80,7,10,0,8,96,0,8,32,0,9,160,0,8,0,0,8,128,0,8,64,0,9,224,80,7,6,0,8,88,0,8,24,0,9,144,83,7,59,0,8,120,0,8,56,0,9,208,81,7,17,0,8,104,0,8,40,0,9,176,0,8,8,0,8,136,0,8,72,0,9,240,80,7,4,0,8,84,0,8,20,85,8,227,83,7,43,0,8,116,0,8,52,0,9,200,81,7,13,0,8,100,0,8,36,0,9,168,0,8,4,0,8,132,0,8,68,0,9,232,80,7,8,0,8,92,0,8,28,0,9,152,84,7,83,0,8,124,0,8,60,0,9,216,82,7,23,0,8,108,0,8,44,0,9,184,0,8,12,0,8,140,0,8,76,0,9,248,80,7,3,0,8,82,0,8,18,85,8,163,83,7,35,0,8,114,0,8,50,0,9,196,81,7,11,0,8,98,0,8,34,0,9,164,0,8,2,0,8,130,0,8,66,0,9,228,80,7,7,0,8,90,0,8,26,0,9,148,84,7,67,0,8,122,0,8,58,0,9,212,82,7,19,0,8,106,0,8,42,0,9,180,0,8,10,0,8,138,0,8,74,0,9,244,80,7,5,0,8,86,0,8,22,192,8,0,83,7,51,0,8,118,0,8,54,0,9,204,81,7,15,0,8,102,0,8,38,0,9,172,0,8,6,0,8,134,0,8,70,0,9,236,80,7,9,0,8,94,0,8,30,0,9,156,84,7,99,0,8,126,0,8,62,0,9,220,82,7,27,0,8,110,0,8,46,0,9,188,0,8,14,0,8,142,0,8,78,0,9,252,96,7,256,0,8,81,0,8,17,85,8,131,82,7,31,0,8,113,0,8,49,0,9,194,80,7,10,0,8,97,0,8,33,0,9,162,0,8,1,0,8,129,0,8,65,0,9,226,80,7,6,0,8,89,0,8,25,0,9,146,83,7,59,0,8,121,0,8,57,0,9,210,81,7,17,0,8,105,0,8,41,0,9,178,0,8,9,0,8,137,0,8,73,0,9,242,80,7,4,0,8,85,0,8,21,80,8,258,83,7,43,0,8,117,0,8,53,0,9,202,81,7,13,0,8,101,0,8,37,0,9,170,0,8,5,0,8,133,0,8,69,0,9,234,80,7,8,0,8,93,0,8,29,0,9,154,84,7,83,0,8,125,0,8,61,0,9,218,82,7,23,0,8,109,0,8,45,0,9,186,0,8,13,0,8,141,0,8,77,0,9,250,80,7,3,0,8,83,0,8,19,85,8,195,83,7,35,0,8,115,0,8,51,0,9,198,81,7,11,0,8,99,0,8,35,0,9,166,0,8,3,0,8,131,0,8,67,0,9,230,80,7,7,0,8,91,0,8,27,0,9,150,84,7,67,0,8,123,0,8,59,0,9,214,82,7,19,0,8,107,0,8,43,0,9,182,0,8,11,0,8,139,0,8,75,0,9,246,80,7,5,0,8,87,0,8,23,192,8,0,83,7,51,0,8,119,0,8,55,0,9,206,81,7,15,0,8,103,0,8,39,0,9,174,0,8,7,0,8,135,0,8,71,0,9,238,80,7,9,0,8,95,0,8,31,0,9,158,84,7,99,0,8,127,0,8,63,0,9,222,82,7,27,0,8,111,0,8,47,0,9,190,0,8,15,0,8,143,0,8,79,0,9,254,96,7,256,0,8,80,0,8,16,84,8,115,82,7,31,0,8,112,0,8,48,0,9,193,80,7,10,0,8,96,0,8,32,0,9,161,0,8,0,0,8,128,0,8,64,0,9,225,80,7,6,0,8,88,0,8,24,0,9,145,83,7,59,0,8,120,0,8,56,0,9,209,81,7,17,0,8,104,0,8,40,0,9,177,0,8,8,0,8,136,0,8,72,0,9,241,80,7,4,0,8,84,0,8,20,85,8,227,83,7,43,0,8,116,0,8,52,0,9,201,81,7,13,0,8,100,0,8,36,0,9,169,0,8,4,0,8,132,0,8,68,0,9,233,80,7,8,0,8,92,0,8,28,0,9,153,84,7,83,0,8,124,0,8,60,0,9,217,82,7,23,0,8,108,0,8,44,0,9,185,0,8,12,0,8,140,0,8,76,0,9,249,80,7,3,0,8,82,0,8,18,85,8,163,83,7,35,0,8,114,0,8,50,0,9,197,81,7,11,0,8,98,0,8,34,0,9,165,0,8,2,0,8,130,0,8,66,0,9,229,80,7,7,0,8,90,0,8,26,0,9,149,84,7,67,0,8,122,0,8,58,0,9,213,82,7,19,0,8,106,0,8,42,0,9,181,0,8,10,0,8,138,0,8,74,0,9,245,80,7,5,0,8,86,0,8,22,192,8,0,83,7,51,0,8,118,0,8,54,0,9,205,81,7,15,0,8,102,0,8,38,0,9,173,0,8,6,0,8,134,0,8,70,0,9,237,80,7,9,0,8,94,0,8,30,0,9,157,84,7,99,0,8,126,0,8,62,0,9,221,82,7,27,0,8,110,0,8,46,0,9,189,0,8,14,0,8,142,0,8,78,0,9,253,96,7,256,0,8,81,0,8,17,85,8,131,82,7,31,0,8,113,0,8,49,0,9,195,80,7,10,0,8,97,0,8,33,0,9,163,0,8,1,0,8,129,0,8,65,0,9,227,80,7,6,0,8,89,0,8,25,0,9,147,83,7,59,0,8,121,0,8,57,0,9,211,81,7,17,0,8,105,0,8,41,0,9,179,0,8,9,0,8,137,0,8,73,0,9,243,80,7,4,0,8,85,0,8,21,80,8,258,83,7,43,0,8,117,0,8,53,0,9,203,81,7,13,0,8,101,0,8,37,0,9,171,0,8,5,0,8,133,0,8,69,0,9,235,80,7,8,0,8,93,0,8,29,0,9,155,84,7,83,0,8,125,0,8,61,0,9,219,82,7,23,0,8,109,0,8,45,0,9,187,0,8,13,0,8,141,0,8,77,0,9,251,80,7,3,0,8,83,0,8,19,85,8,195,83,7,35,0,8,115,0,8,51,0,9,199,81,7,11,0,8,99,0,8,35,0,9,167,0,8,3,0,8,131,0,8,67,0,9,231,80,7,7,0,8,91,0,8,27,0,9,151,84,7,67,0,8,123,0,8,59,0,9,215,82,7,19,0,8,107,0,8,43,0,9,183,0,8,11,0,8,139,0,8,75,0,9,247,80,7,5,0,8,87,0,8,23,192,8,0,83,7,51,0,8,119,0,8,55,0,9,207,81,7,15,0,8,103,0,8,39,0,9,175,0,8,7,0,8,135,0,8,71,0,9,239,80,7,9,0,8,95,0,8,31,0,9,159,84,7,99,0,8,127,0,8,63,0,9,223,82,7,27,0,8,111,0,8,47,0,9,191,0,8,15,0,8,143,0,8,79,0,9,255],w=[80,5,1,87,5,257,83,5,17,91,5,4097,81,5,5,89,5,1025,85,5,65,93,5,16385,80,5,3,88,5,513,84,5,33,92,5,8193,82,5,9,90,5,2049,86,5,129,192,5,24577,80,5,2,87,5,385,83,5,25,91,5,6145,81,5,7,89,5,1537,85,5,97,93,5,24577,80,5,4,88,5,769,84,5,49,92,5,12289,82,5,13,90,5,3073,86,5,193,192,5,24577],x=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],y=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,112,112],z=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],A=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],B=15;b.inflate_trees_fixed=function(a,b,c,d){return a[0]=t,b[0]=u,c[0]=v,d[0]=w,i};var C=0,D=1,E=2,F=3,G=4,H=5,I=6,J=7,K=8,L=9,M=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],N=0,O=1,P=2,Q=3,R=4,S=5,T=6,U=7,V=8,W=9,X=32,Y=8,Z=0,$=1,_=2,aa=3,ba=4,ca=5,da=6,ea=7,fa=12,ga=13,ha=[0,0,255,255];f.prototype={inflateInit:function(a){var b=this;return b.istate=new e,a||(a=h),b.istate.inflateInit(b,a)},inflate:function(a){var b=this;return b.istate?b.istate.inflate(b,a):l},inflateEnd:function(){var a=this;if(!a.istate)return l;var b=a.istate.inflateEnd(a);return a.istate=null,b},inflateSync:function(){var a=this;return a.istate?a.istate.inflateSync(a):l},inflateSetDictionary:function(a,b){var c=this;return c.istate?c.istate.inflateSetDictionary(c,a,b):l},read_byte:function(a){var b=this;return b.next_in.subarray(a,a+1)[0]},read_buf:function(a,b){var c=this;return c.next_in.subarray(a,a+b)}};var ia;a.zip?a.zip.Inflater=g:(ia=new g,a.addEventListener("message",function(b){var c=b.data;c.append&&a.postMessage({onappend:!0,data:ia.append(c.data,function(b){a.postMessage({progress:!0,current:b})})}),c.flush&&(ia.flush(),a.postMessage({onflush:!0}))},!1))},O.esri.TPK.___test=O.esri.TPK.inflate.toString(),O.esri.TPK.___blobURL=URL.createObjectURL(new Blob(["(",O.esri.TPK.___test,")(this)"],{type:"application/javascript"})),O.esri.zip.workerScriptsPath=O.esri.TPK.___blobURL,O.esri.TPK.X2JS=function(a){"use strict";function b(){void 0===a.escapeMode&&(a.escapeMode=!0),a.attributePrefix=a.attributePrefix||"_",a.arrayAccessForm=a.arrayAccessForm||"none",a.emptyNodeForm=a.emptyNodeForm||"text",void 0===a.enableToStringFunc&&(a.enableToStringFunc=!0),a.arrayAccessFormPaths=a.arrayAccessFormPaths||[],void 0===a.skipEmptyTextNodesForObj&&(a.skipEmptyTextNodesForObj=!0),void 0===a.stripWhitespaces&&(a.stripWhitespaces=!0),a.datetimeAccessFormPaths=a.datetimeAccessFormPaths||[]}function c(){function a(a){var b=String(a);return 1===b.length&&(b="0"+b),b}"function"!=typeof String.prototype.trim&&(String.prototype.trim=function(){return this.replace(/^\s+|^\n+|(\s|\n)+$/g,"")}),"function"!=typeof Date.prototype.toISOString&&(Date.prototype.toISOString=function(){return this.getUTCFullYear()+"-"+a(this.getUTCMonth()+1)+"-"+a(this.getUTCDate())+"T"+a(this.getUTCHours())+":"+a(this.getUTCMinutes())+":"+a(this.getUTCSeconds())+"."+String((this.getUTCMilliseconds()/1e3).toFixed(3)).slice(2,5)+"Z"})}function d(a){var b=a.localName;return null==b&&(b=a.baseName),(null==b||""==b)&&(b=a.nodeName),b}function e(a){return a.prefix}function f(a){return"string"==typeof a?a.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/"):a}function g(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(///g,"/")}function h(b,c,d){switch(a.arrayAccessForm){case"property":b[c]instanceof Array?b[c+"_asArray"]=b[c]:b[c+"_asArray"]=[b[c]]}if(!(b[c]instanceof Array)&&a.arrayAccessFormPaths.length>0){for(var e=0;e1&&c.setMilliseconds(d[1]),b[6]&&b[7]){var e=60*b[6]+Number(b[7]),f=/\d\d-\d\d:\d\d$/.test(a)?"-":"+";e=0+("-"==f?-1*e:e),c.setMinutes(c.getMinutes()-e-c.getTimezoneOffset())}else-1!==a.indexOf("Z",a.length-1)&&(c=new Date(Date.UTC(c.getFullYear(),c.getMonth(),c.getDate(),c.getHours(),c.getMinutes(),c.getSeconds(),c.getMilliseconds())));return c}function j(b,c,d){if(a.datetimeAccessFormPaths.length>0){for(var e=d.split(".#")[0],f=0;f1&&null!=f.__text&&a.skipEmptyTextNodesForObj&&(a.stripWhitespaces&&""==f.__text||""==f.__text.trim())&&delete f.__text,delete f.__cnt,!a.enableToStringFunc||null==f.__text&&null==f.__cdata||(f.toString=function(){return(null!=this.__text?this.__text:"")+(null!=this.__cdata?this.__cdata:"")}),f}return b.nodeType==w.TEXT_NODE||b.nodeType==w.CDATA_SECTION_NODE?b.nodeValue:void 0}function l(b,c,d,e){var g="<"+(null!=b&&null!=b.__prefix?b.__prefix+":":"")+c;if(null!=d)for(var h=0;h":">"}function m(a,b){return""}function n(a,b){return-1!==a.indexOf(b,a.length-b.length)}function o(b,c){return"property"==a.arrayAccessForm&&n(c.toString(),"_asArray")||0==c.toString().indexOf(a.attributePrefix)||0==c.toString().indexOf("__")||b[c]instanceof Function?!0:!1}function p(a){var b=0;if(a instanceof Object)for(var c in a)o(a,c)||b++;return b}function q(b){var c=[];if(b instanceof Object)for(var d in b)-1==d.toString().indexOf("__")&&0==d.toString().indexOf(a.attributePrefix)&&c.push(d);return c}function r(b){var c="";return null!=b.__cdata&&(c+=""),null!=b.__text&&(c+=a.escapeMode?f(b.__text):b.__text),c}function s(b){var c="";return b instanceof Object?c+=r(b):null!=b&&(c+=a.escapeMode?f(b):b),c}function t(a,b,c){var d="";if(0==a.length)d+=l(a,b,c,!0);else for(var e=0;e0)for(var d in a)if(!o(a,d)){var e=a[d],f=q(e);if(null==e||void 0==e)b+=l(e,d,f,!0);else if(e instanceof Object)if(e instanceof Array)b+=t(e,d,f);else if(e instanceof Date)b+=l(e,d,f,!1),b+=e.toISOString(),b+=m(e,d);else{var g=p(e);g>0||null!=e.__text||null!=e.__cdata?(b+=l(e,d,f,!1),b+=u(e),b+=m(e,d)):b+=l(e,d,f,!0)}else b+=l(e,d,f,!1),b+=s(e),b+=m(e,d)}return b+=s(a)}var v="1.1.5",a=a||{};b(),c();var w={ELEMENT_NODE:1,TEXT_NODE:3,CDATA_SECTION_NODE:4,COMMENT_NODE:8,DOCUMENT_NODE:9};this.parseXmlString=function(a){var b=window.ActiveXObject||"ActiveXObject"in window;if(void 0===a)return null;var c;if(window.DOMParser){var d=new window.DOMParser,e=null;if(!b)try{e=d.parseFromString("INVALID","text/xml").childNodes[0].namespaceURI}catch(f){e=null}try{c=d.parseFromString(a,"text/xml"),null!=e&&c.getElementsByTagNameNS(e,"parsererror").length>0&&(c=null)}catch(f){c=null}}else 0==a.indexOf("")+2)),c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(a);return c},this.asArray=function(a){return a instanceof Array?a:[a]},this.toXmlDateTime=function(a){return a instanceof Date?a.toISOString():"number"==typeof a?new Date(a).toISOString():null},this.asDateTime=function(a){return"string"==typeof a?i(a):a},this.xml2json=function(a){return k(a)},this.xml_str2json=function(a){var b=this.parseXmlString(a);return null!=b?this.xml2json(b):null},this.json2xml_str=function(a){return u(a)},this.json2xml=function(a){var b=this.json2xml_str(a);return this.parseXmlString(b)},this.getVersion=function(){return v}}; \ No newline at end of file +define(["dojo/_base/declare","esri/geometry/Extent","dojo/query","esri/SpatialReference","esri/layers/TileInfo","esri/layers/TiledMapServiceLayer","dojo/Deferred","dojo/promise/all","dojo/Evented"],function(a,b,c,d,e,f,g,h,i){return a("O.esri.TPK.TPKLayer",[f,i],{map:null,store:null,MAX_DB_SIZE:75,TILE_PATH:"",RECENTER_DELAY:350,PARSING_ERROR:"parsingError",DB_INIT_ERROR:"dbInitError",DB_FULL_ERROR:"dbFullError",NO_SUPPORT_ERROR:"libNotSupportedError",PROGRESS_START:"start",PROGRESS_END:"end",WINDOW_VALIDATED:"windowValidated",DB_VALIDATED:"dbValidated",DATABASE_ERROR_EVENT:"databaseErrorEvent",VALIDATION_EVENT:"validationEvent",PROGRESS_EVENT:"progress",_maxDBSize:75,_isDBWriteable:!0,_isDBValid:!1,_autoCenter:null,_fileEntriesLength:0,_inMemTilesObject:null,_inMemTilesObjectLength:0,_zeroLengthFileCounter:0,constructor:function(){this._self=this,this._inMemTilesIndex=[],this._inMemTilesObject={},this.store=new O.esri.Tiles.TilesStore,this._validate()},extend:function(a){this._fileEntriesLength=a.length,this.emit(this.PROGRESS_EVENT,this.PROGRESS_START),this._parseInMemFiles(a,function(){this._parseConfCdi(function(a){this.initialExtent=this.fullExtent=a,this._parseConfXml(function(a){this.tileInfo=new e(a),this.spatialReference=new d({wkid:this.tileInfo.spatialReference.wkid}),this.loaded=!0,this.onLoad(this),this.emit(this.PROGRESS_EVENT,this.PROGRESS_END)}.bind(this._self))}.bind(this._self))}.bind(this._self))},getTileUrl:function(a,b,d){this.emit(this.PROGRESS_EVENT,this.PROGRESS_START) +var e=this._self.TILE_PATH+"_alllayers",f=this._getCacheFilePath(e,a,b,d) +if(this._inMemTilesObject!={}){var g="void:/"+a+"/"+b+"/"+d +return null==this.map&&(this.map=this.getMap()),null==this._autoCenter&&(this._autoCenter=new O.esri.TPK.autoCenterMap(this.map,this.RECENTER_DELAY),this._autoCenter.init()),this._getInMemTiles(f,e,a,b,d,g,function(a,b,d){var e=c("img[src="+b+"]")[0] +"undefined"==typeof e&&(e=new Image) +var f +if(a){var g="data:image/png;base64," +switch(this.tileInfo.format){case"JPEG":f="data:image/jpg;base64,"+a +break +case"PNG":f=g+a +break +case"PNG8":f=g+a +break +case"PNG24":f=g+a +break +case"PNG32":f=g+a +break +default:f="data:image/jpg;base64,"+a}e.style.borderColor="blue"}else e.style.borderColor="green",f="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAABQdJREFUeNrs2yFv6mocwOH/ualYRUVJRrKKCRATCCZqJ/mOfKQJBGaiYkcguoSJigoQTc4VN222Mdhu7l0ysudJjqFAD13669u37a/lcvkngB8piYhYLBa2BPxAf9kEIACAAAACAAgAIACAAAACAAgAIACAAAACAAgAIACAAAACAAgAIACAAAACAAgAIACAAAACAAgAIACAAAACAAgAIACAAAACAAgAIACAAAACAAgACAAgAIAAAAIACAAgAIAAAAIACAAgAIAAAAIACAAgAIAAAAIACAAgAIAAAAIACAAgAIAAAAIACAAgAIAAAAIACAAgAIAAAAIACAAgAIAAAAIACAAIACAAgAAAAgAIACAAgAAAAgAIACAAgAAAAgAIACAAgAAAAgAIACAAgAAAAgAIACAAgAAAAgAIACAAgAAAAgAIACAAgAAAAgAIACAAgAAAAgAIAPxsiU3wfbRtG1mWnVzedV3kef7q9a7rYrvdxm63i4iILMtiNBpFkiQfftdnZFkWbdtGRAzr7j+fZdnR9Xy0jiRJTv5eBOBHqaoqsiyLm5ubo8ubponFYjG8Vtd1VFV1sKMlSRI3NzdRFMXJ7/qMsixjtVpFRAzr7j9fluVBkD67jjzPoyxLf3gBoLfZbGI8Hh/dqV6q6zoeHh4iSZKYTCYxGo0iImK73Q7Luq6L6+vrg88WRfFqHfv9Puq6jjRN4+rq6tV7Ly4u/tNvKori3e9I09QfXAB4a71ex93d3ckhfNd1UVXVcIR+OZTO8zyKooj7+/uoqiouLy8Pdra3I4OmaaKu67i4uIjpdPq//p63seH7MAn4DXVdF+v1+sOjf390f+88Osuy4ci/2WxsVATgXEwmk2ia5uSOu91uIyJiPB4ffU+/rJ/AA6cAZ2A6ncbz83NUVRV5nr97hO8n104Nrftln53s+ypVVR2czpj8MwLghPl8HkmSDBN556xt22ia5tU/jAA4IU3TmE6nUVVVVFUVs9nsbH/LqUuFGAFwxPX1deR5HnVdD+f8LwPx0fl9f2OQy20IwJm6vb0dTgX2+/3wej8vcCoA/VDb3XYIwLmeoyVJzGaz6LpuOKJHRFxeXkbEP5cDj+mX9e8FAThD4/H44HJfURSRpmk0TROPj48Hn3l4eIimaSJN06O3A4NJwDMxm82ibdtXo4D5fB6r1Sp+//4dz8/Pw5H+6ekpdrtdJEkS8/n8S/9f713ie3vaceo9x557QAB451Sgfyin34HKshweunk5HzAej2MymXz5+f9nbjJyI9L39Wu5XP55+XQZ39uxR4Z3u90wSXjqEV0wAjhjx47oaZq63Me/ZhIQBAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAAbAJQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAvqe/BwCeKjUweoA8pQAAAABJRU5ErkJggg==" +return e.style.visibility="visible",e.src=f,this.emit(this.PROGRESS_EVENT,this.PROGRESS_END),""}.bind(this._self)),g}},setMaxDBSize:function(a){var b=/^\d+$/ +b.test(a)&&a<=this.MAX_DB_SIZE&&(this._maxDBSize=a)},getDBSize:function(a){this.store.usedSpace(function(b,c){a(b,c)}.bind(this))},setDBWriteable:function(a){this._isDBWriteable=a},isDBValid:function(){return this._validate(),this._isDBValid},loadFromURL:function(a,b){this.isDBValid()?this.store.store(a,function(a,c){a?b(!0,""):b(!1,c)}):b(!1,"not supported")},_validate:function(){window.File||window.FileReader||window.Blob||window.btoa||window.DataView?this.emit(this.VALIDATION_EVENT,{msg:this.WINDOW_VALIDATED,err:null}):this.emit(this.VALIDATION_EVENT,{msg:this.NO_SUPPORT_ERROR,err:null}),this.store.isSupported()?this.store.init(function(a){a===!1?this.emit(this.DATABASE_ERROR_EVENT,{msg:this.DB_INIT_ERROR,err:null}):this.store.usedSpace(function(a,b){var c=this._bytes2MBs(a.sizeBytes) +c>this.MAX_DB_SIZE&&this.emit(this.DATABASE_ERROR_EVENT,{msg:this.DB_FULL_ERROR,err:b}),this.emit(this.VALIDATION_EVENT,{msg:this.DB_VALIDATED,err:null}),this._isDBValid=!0}.bind(this))}.bind(this)):this.emit(this.VALIDATION_EVENT,{msg:this.NO_SUPPORT_ERROR,err:null})},_parseInMemFiles:function(a,b){var c=this._fileEntriesLength +this._zeroLengthFileCounter=0 +for(var d=[],e=0;c>e;e++){var f=new g,i=a[e].filename.toLocaleUpperCase(),j=i.indexOf("_ALLLAYERS",0);-1!=j&&(this.TILE_PATH=i.slice(0,j)),0===a[e].compressedSize&&this._zeroLengthFileCounter++ +var k=i.indexOf("CONF.CDI",0),l=i.indexOf("CONF.XML",0),m=i.indexOf("BUNDLE",0),n=i.indexOf("BUNDLX",0);-1!=k||-1!=l?this._unzipConfFiles(a,e,f,function(a,b){a.resolve(b)}):-1!=m||-1!=n?this._unzipTileFiles(a,e,f,function(a,b){a.resolve(b)}):f.resolve(e),d.push(f)}h(d).then(function(a){b&&b(a)})},ObjectSize:function(a){var b,c=0 +for(b in a)a.hasOwnProperty(b)&&c++ +return c},_unzipConfFiles:function(a,b,c,d){a[b].getData(new O.esri.zip.TextWriter(b),function(b){this._inMemTilesIndex.push("blank") +var e=a[b.token].filename.toLocaleUpperCase() +this._inMemTilesObject[e]=b.string +var f=this.ObjectSize(this._inMemTilesObject) +f>0&&d(c,b.token)}.bind(this))},_unzipTileFiles:function(a,b,c,d){var e=this +a[b].getData(new O.esri.zip.BlobWriter(b),function(b){if(0!==b.size){var f=new FileReader +f.token=b.token,f.onerror=function(a){e.emit(e.PARSING_ERROR,{msg:"Error parsing file: ",err:a.target.error})},f.onloadend=function(g){if(void 0!==f.token){e._inMemTilesIndex.push("blank") +var h=a[f.token].filename.toLocaleUpperCase() +e._inMemTilesObject[h]=f.result +var i=e.ObjectSize(e._inMemTilesObject) +i>0&&d(c,b.token)}},f.readAsArrayBuffer(b)}})},_parseConfCdi:function(a){var c=this._inMemTilesObject[this.TILE_PATH+"CONF.CDI"],e=new O.esri.TPK.X2JS,f=e.xml_str2json(c),g=f.EnvelopeN,h=parseFloat(g.XMin),i=parseFloat(g.YMin),j=parseFloat(g.XMax),k=parseFloat(g.YMax),l=parseInt(g.SpatialReference.WKID),m=new b(h,i,j,k,new d({wkid:l})) +a(m)},_parseConfXml:function(a){var b=this._inMemTilesObject[this.TILE_PATH+"CONF.XML"],c=new O.esri.TPK.X2JS,d=c.xml_str2json(b),e=d.CacheInfo,f={} +f.rows=parseInt(e.TileCacheInfo.TileRows),f.cols=parseInt(e.TileCacheInfo.TileCols),f.dpi=parseInt(e.TileCacheInfo.DPI),f.format=e.TileImageInfo.CacheTileFormat,f.compressionQuality=parseInt(e.TileImageInfo.CompressionQuality),f.origin={x:parseInt(e.TileCacheInfo.TileOrigin.X),y:parseInt(e.TileCacheInfo.TileOrigin.Y)},f.spatialReference={wkid:parseInt(e.TileCacheInfo.SpatialReference.WKID)} +for(var g=e.TileCacheInfo.LODInfos.LODInfo,h=[],i=0;im;m+=3)f=i[m]<<16|i[m+1]<<8|i[m+2],b=(16515072&f)>>18,c=(258048&f)>>12,d=(4032&f)>>6,e=63&f,g+=h[b]+h[c]+h[d]+h[e] +return 1==k?(f=i[l],b=(252&f)>>2,c=(3&f)<<4,g+=h[b]+h[c]+"=="):2==k&&(f=i[l]<<8|i[l+1],b=(64512&f)>>10,c=(1008&f)>>4,d=(15&f)<<2,g+=h[b]+h[c]+h[d]+"="),g},_buffer2Base64:function(a,b,c){var d=new DataView(a,b),e=d.getInt32(0,!0),f=d.buffer.slice(b+4,b+4+e),g=this._base64ArrayBuffer(f) +c(g)},_int2HexString:function(a){var b=a.toString(16).toUpperCase() +return 1===b.length?"000"+b:2===b.length?"00"+b:3===b.length?"0"+b:b.substr(0,b.length)},_getOffset:function(a,b,c,d,e){var f=128*(c-e)+(b-d) +return 16+5*f},_getCacheFilePath:function(a,b,c,d){var e=[] +return e.push(a),e.push("/"),e.push("L"),e.push(10>b?"0"+b:b),e.push("/"),e.push("R"),e.push(this._int2HexString(c)),e.push("C"),e.push(this._int2HexString(d)),e.join("")},_bytes2MBs:function(a){return(a>>>20)+"."+(2046&a)}})}),"undefined"!=typeof O?O.esri.TPK={}:(O={},O.esri={TPK:{},Tiles:{}}),O.esri.Tiles.TilesStore=function(){this._db=null,this.dbName="offline_tile_store",this.objectStoreName="tilepath",this.isSupported=function(){return window.indexedDB||window.openDatabase?!0:!1},this.store=function(a,b){try{var c=this._db.transaction([this.objectStoreName],"readwrite") +c.oncomplete=function(){b(!0)},c.onerror=function(a){b(!1,a.target.error.message)} +var d=c.objectStore(this.objectStoreName),e=d.put(a) +e.onsuccess=function(){}}catch(f){b(!1,f.stack)}},this.retrieve=function(a,b){if(null!==this._db){var c=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName),d=c.get(a) +d.onsuccess=function(a){var c=a.target.result +void 0===c?b(!1,"not found"):b(!0,c)},d.onerror=function(a){b(!1,a)}}},this.deleteAll=function(a){if(null!==this._db){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear() +b.onsuccess=function(){a(!0)},b.onerror=function(b){a(!1,b)}}else a(!1,null)},this["delete"]=function(a,b){if(null!==this._db){var c=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName)["delete"](a) +c.onsuccess=function(){b(!0)},c.onerror=function(a){b(!1,a)}}else b(!1,null)},this.getAllTiles=function(a){if(null!==this._db){var b=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor() +b.onsuccess=function(b){var c=b.target.result +if(c){var d=c.value.url,e=c.value.img +a(d,e,null),c["continue"]()}else a(null,null,"end")}.bind(this),b.onerror=function(b){a(null,null,b)}}else a(null,null,"no db")},this.usedSpace=function(a){if(null!==this._db){var b={sizeBytes:0,tileCount:0},c=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor() +c.onsuccess=function(c){var d=c.target.result +if(d){var e=d.value,f=JSON.stringify(e) +b.sizeBytes+=this._stringBytes(f),b.tileCount+=1,d["continue"]()}else a(b,null)}.bind(this),c.onerror=function(b){a(null,b)}}else a(null,null)},this._stringBytes=function(a){return a.length},this.init=function(a){var b=indexedDB.open(this.dbName,4) +a=a||function(a){}.bind(this),b.onerror=function(b){a(!1,b.target.errorCode)}.bind(this),b.onupgradeneeded=function(a){var b=a.target.result +b.objectStoreNames.contains(this.objectStoreName)&&b.deleteObjectStore(this.objectStoreName),b.createObjectStore(this.objectStoreName,{keyPath:"url"})}.bind(this),b.onsuccess=function(b){this._db=b.target.result,a(!0)}.bind(this)}},function(a){function b(){var a=-1,b=this +b.append=function(c){var d,e=b.table +for(d=0;d>>8^e[255&(a^c[d])]},b.get=function(){return~a}}function c(a,b,c){return a.slice?a.slice(b,b+c):a.webkitSlice?a.webkitSlice(b,b+c):a.mozSlice?a.mozSlice(b,b+c):a.msSlice?a.msSlice(b,b+c):void 0}function d(a,b){var c,d +return c=new ArrayBuffer(a),d=new Uint8Array(c),b&&d.set(b,0),{buffer:c,array:d,view:new DataView(c)}}function e(){}function f(a){function b(b,c){var f=new Blob([a],{type:M}) +d=new h(f),d.init(function(){e.size=d.size,b()},c)}function c(a,b,c,e){d.readUint8Array(a,b,c,e)}var d,e=this +e.size=0,e.init=b,e.readUint8Array=c}function g(b){function c(a){for(var c=b.length;"="==b.charAt(c-1);)c-- +f=b.indexOf(",")+1,g.size=Math.floor(.75*(c-f)),a()}function e(c,e,g){var h,i=d(e),j=4*Math.floor(c/3),k=4*Math.ceil((c+e)/3),l=a.atob(b.substring(j+f,k+f)),m=c-3*Math.floor(j/4) +for(h=m;m+e>h;h++)i.array[h-m]=l.charCodeAt(h) +g(i.array)}var f,g=this +g.size=0,g.init=c,g.readUint8Array=e}function h(a){function b(b){this.size=a.size,b()}function d(b,d,e,f){var g=new FileReader +g.onload=function(a){e(new Uint8Array(a.target.result))},g.onerror=f,g.readAsArrayBuffer(c(a,b,d))}var e=this +e.size=0,e.init=b,e.readUint8Array=d}function i(){}function j(a,b){function c(a){f=new Blob([],{type:M}),a()}function d(a,b){f=new Blob([f,A?a:a.buffer],{type:M}),b()}function e(c,d){var e=new FileReader +e.onload=function(b){var d={string:b.target.result,token:a} +c(d)},e.onerror=d,e.readAsText(f,b)}var f,g=this +g.init=c,g.writeUint8Array=d,g.getData=e}function k(b){function c(a){g+="data:"+(b||"")+";base64,",a()}function d(b,c){var d,e=h.length,f=h +for(h="",d=0;d<3*Math.floor((e+b.length)/3)-e;d++)f+=String.fromCharCode(b[d]) +for(;d2?g+=a.btoa(f):h=f,c()}function e(b){b(g+a.btoa(h))}var f=this,g="",h="" +f.init=c,f.writeUint8Array=d,f.getData=e}function l(a,b){function c(a){f=new Blob([],{type:b}),a()}function d(c,d){f=new Blob([f,A?c:c.buffer],{type:b}),f.token=a,d()}function e(a){a(f)}var f,g=this +g.init=c,g.writeUint8Array=d,g.getData=e}function m(a,b,c,d,e,f,g,h,i,j){function k(){a.removeEventListener(N,l,!1),h(o)}function l(a){var b=a.data,d=b.data +b.onappend&&(o+=d.length,c.writeUint8Array(d,function(){f(!1,d),m()},j)),b.onflush&&(d?(o+=d.length,c.writeUint8Array(d,function(){f(!1,d),k()},j)):k()),b.progress&&g&&g(n+b.current,e)}function m(){n=p*J,e>n?b.readUint8Array(d+n,Math.min(J,e-n),function(b){a.postMessage({append:!0,data:b}),p++,g&&g(n,e),f(!0,b)},i):a.postMessage({flush:!0})}var n,o,p=0 +o=0,a.addEventListener(N,l,!1),m()}function n(a,b,c,d,e,f,g,h,i,j){function k(){var o +l=m*J,e>l?b.readUint8Array(d+l,Math.min(J,e-l),function(b){var h=a.append(b,function(){g&&g(d+l,e)}) +n+=h.length,f(!0,b),c.writeUint8Array(h,function(){f(!1,h),m++,setTimeout(k,1)},j),g&&g(l,e)},i):(o=a.flush(),o?(n+=o.length,c.writeUint8Array(o,function(){f(!1,o),h(n)},j)):h(n))}var l,m=0,n=0 +k()}function o(c,d,e,f,g,h,i,j,k){function l(a,b){g&&!a&&q.append(b)}function o(a){h(a,q.get())}var p,q=new b +return a.zip.useWebWorkers?(p=new Worker(a.zip.workerScriptsPath+K),m(p,c,d,e,f,l,i,o,j,k)):n(new a.zip.Inflater,c,d,e,f,l,i,o,j,k),p}function p(c,d,e,f,g,h,i){function j(a,b){a&&p.append(b)}function k(a){f(a,p.get())}function l(){o.removeEventListener(N,l,!1),m(o,c,d,0,c.size,j,g,k,h,i)}var o,p=new b +return a.zip.useWebWorkers?(o=new Worker(a.zip.workerScriptsPath+L),o.addEventListener(N,l,!1),o.postMessage({init:!0,level:e})):n(new a.zip.Deflater,c,d,0,c.size,j,g,k,h,i),o}function q(a,c,d,e,f,g,h,i,j){function k(){var b=l*J +e>b?a.readUint8Array(d+b,Math.min(J,e-b),function(a){f&&m.append(a),h&&h(b,e,a),c.writeUint8Array(a,function(){l++,k()},j)},i):g(e,m.get())}var l=0,m=new b +k()}function r(a){var b,c,d="",e=["Ç","ü","é","â","ä","à","å","ç","ê","ë","è","ï","î","ì","Ä","Å","É","æ","Æ","ô","ö","ò","û","ù","ÿ","Ö","Ü","ø","£","Ø","×","ƒ","á","í","ó","ú","ñ","Ñ","ª","º","¿","®","¬","½","¼","¡","«","»","_","_","_","¦","¦","Á","Â","À","©","¦","¦","+","+","¢","¥","+","+","-","-","+","-","+","ã","Ã","+","+","-","-","¦","-","+","¤","ð","Ð","Ê","Ë","È","i","Í","Î","Ï","+","+","_","_","¦","Ì","_","Ó","ß","Ô","Ò","õ","Õ","µ","þ","Þ","Ú","Û","Ù","ý","Ý","¯","´","­","±","_","¾","¶","§","÷","¸","°","¨","·","¹","³","²","_"," "] +for(b=0;b127?e[c-128]:String.fromCharCode(c) +return d}function s(a){return decodeURIComponent(escape(a))}function t(a){var b,c="" +for(b=0;b>16,c=65535&a +try{return new Date(1980+((65024&b)>>9),((480&b)>>5)-1,31&b,(63488&c)>>11,(2016&c)>>5,2*(31&c),0)}catch(d){}}function v(a,b,c,d,e){return a.version=b.view.getUint16(c,!0),a.bitFlag=b.view.getUint16(c+2,!0),a.compressionMethod=b.view.getUint16(c+4,!0),a.lastModDateRaw=b.view.getUint32(c+6,!0),a.lastModDate=u(a.lastModDateRaw),1===(1&a.bitFlag)?void e(C):((d||8!=(8&a.bitFlag))&&(a.crc32=b.view.getUint32(c+10,!0),a.compressedSize=b.view.getUint32(c+14,!0),a.uncompressedSize=b.view.getUint32(c+18,!0)),4294967295===a.compressedSize||4294967295===a.uncompressedSize?void e(D):(a.filenameLength=b.view.getUint16(c+22,!0),void(a.extraFieldLength=b.view.getUint16(c+24,!0))))}function w(a,b){function c(){}function e(c,f){a.readUint8Array(a.size-c,c,function(a){var b=d(a.length,a).view +1347093766!=b.getUint32(0)?e(c+1,f):f(b)},function(){b(E)})}return c.prototype.getData=function(c,e,f,g){function h(a,b){m&&m.terminate(),m=null,a&&a(b)}function i(a){var b=d(4) +return b.view.setUint32(0,a),n.crc32==b.view.getUint32(0)}function j(a,b){g&&!i(b)?k():c.getData(function(a){h(e,a)})}function k(){h(b,H)}function l(){h(b,G)}var m,n=this +a.readUint8Array(n.offset,30,function(e){var h,i=d(e.length,e) +return 1347093252!=i.view.getUint32(0)?void b(B):(v(n,i,4,!1,b),h=n.offset+30+n.filenameLength+n.extraFieldLength,void c.init(function(){0===n.compressionMethod?q(a,c,h,n.compressedSize,g,j,f,k,l):m=o(a,c,h,n.compressedSize,g,j,f,k,l)},l))},k)},{getEntries:function(f){return a.size<22?void b(B):void e(22,function(e){var g,h +g=e.getUint32(16,!0),h=e.getUint16(8,!0),a.readUint8Array(g,a.size-g,function(a){var e,g,i,j,k=0,l=[],m=d(a.length,a) +for(e=0;h>e;e++){if(g=new c,1347092738!=m.view.getUint32(k))return void b(B) +v(g,m,k+6,!0,b),g.commentLength=m.view.getUint16(k+32,!0),g.directory=16==(16&m.view.getUint8(k+38)),g.offset=m.view.getUint32(k+42,!0),i=t(m.array.subarray(k+46,k+46+g.filenameLength)),g.filename=2048===(2048&g.bitFlag)?s(i):r(i),g.directory||"/"!=g.filename.charAt(g.filename.length-1)||(g.directory=!0),j=t(m.array.subarray(k+46+g.filenameLength+g.extraFieldLength,k+46+g.filenameLength+g.extraFieldLength+g.commentLength)),g.comment=2048===(2048&g.bitFlag)?s(j):r(j),l.push(g),k+=46+g.filenameLength+g.extraFieldLength+g.commentLength}f(l)},function(){b(E)})})},close:function(a){a&&a()}}}function x(a){return unescape(encodeURIComponent(a))}function y(a){var b,c=[] +for(b=0;ba;a++){for(c=a,b=0;8>b;b++)1&c?c=c>>>1^3988292384:c>>>=1 +d[a]=c}return d}(),f.prototype=new e,f.prototype.constructor=f,g.prototype=new e,g.prototype.constructor=g,h.prototype=new e,h.prototype.constructor=h,i.prototype.getData=function(a){a(this.data)},j.prototype=new i,j.prototype.constructor=j,k.prototype=new i,k.prototype.constructor=k,l.prototype=new i,l.prototype.constructor=l,a.zip={Reader:e,Writer:i,BlobReader:h,Data64URIReader:g,TextReader:f,BlobWriter:l,Data64URIWriter:k,TextWriter:j,createReader:function(a,b,c){a.init(function(){b(w(a,c))},c)},createWriter:function(a,b,c,d){a.init(function(){b(z(a,c,d))},c)},workerScriptsPath:"",useWebWorkers:!0}}(O.esri),O.esri.TPK.autoCenterMap=function(a,b){function c(a){var b="onorientationchange"in window,c=b?"orientationchange":"resize" +window.addEventListener(c,e(function(){d()},a))}function d(){require(["esri/geometry/Point","esri/SpatialReference"],function(b,c){var d=i().split(","),e=a.spatialReference.wkid,f=null +4326==e?f=new b(d[1],d[0]):102100==e&&(f=new b(d[0],d[1],new c({wkid:e}))),a.centerAt(f)})}function e(a,b,c){var d +return function(){var e=this,f=arguments +clearTimeout(d),d=setTimeout(function(){d=null,c||a.apply(e,f)},b),c&&!d&&a.apply(e,f)}}function f(){a.on("pan-end",function(){var b=a.extent.getCenter() +h(b.x,b.y,a.spatialReference.wkid)})}function g(){a.on("zoom-end",function(){var b=a.extent.getCenter() +h(b.x,b.y,a.spatialReference.wkid),a.setZoom(a.getZoom())})}function h(a,b,c){localStorage.setItem("_centerPtX",a),localStorage.setItem("_centerPtY",b),localStorage.setItem("_spatialReference",c)}function i(){var a=null +try{a=localStorage.getItem("_centerPtX")+","+localStorage.getItem("_centerPtY")+","+localStorage.getItem("_spatialReference")}catch(b){}return a}this.init=function(){f(),g(),c(b) +var d=a.extent.getCenter() +h(d.x,d.y,a.spatialReference.wkid)}},O.esri.TPK.inflate=function(a){function b(){function a(a,b,c,d,j,k,l,n,p,r,s){var t,u,v,w,x,y,z,A,C,D,E,F,G,H,I +D=0,x=c +do e[a[b+D]]++,D++,x-- +while(0!==x) +if(e[0]==c)return l[0]=-1,n[0]=0,i +for(A=n[0],y=1;B>=y&&0===e[y];y++);for(z=y,y>A&&(A=y),x=B;0!==x&&0===e[x];x--);for(v=x,A>x&&(A=x),n[0]=A,H=1<y;y++,H<<=1)if((H-=e[y])<0)return m +if((H-=e[x])<0)return m +for(e[x]+=H,h[1]=y=0,D=1,G=2;0!==--x;)h[G]=y+=e[D],G++,D++ +x=0,D=0 +do 0!==(y=a[b+D])&&(s[h[y]++]=x),D++ +while(++x=z;z++)for(t=e[z];0!==t--;){for(;z>F+A;){if(w++,F+=A,I=v-F,I=I>A?A:I,(u=1<<(y=z-F))>t+1&&(u-=t+1,G=z,I>y))for(;++yq)return m +g[w]=E=r[0],r[0]+=I,0!==w?(h[w]=x,f[0]=y,f[1]=A,y=x>>>F-A,f[2]=E-g[w-1]-y,p.set(f,3*(g[w-1]+y))):l[0]=E}for(f[1]=z-F,D>=c?f[0]=192:s[D]>>F;I>y;y+=u)p.set(f,3*(E+y)) +for(y=1<>>=1)x^=y +for(x^=y,C=(1<b;b++)d[b]=0 +for(b=0;B+1>b;b++)e[b]=0 +for(b=0;3>b;b++)f[b]=0 +g.set(e.subarray(0,B),0),h.set(e.subarray(0,B+1),0)}var c,d,e,f,g,h,j=this +j.inflate_trees_bits=function(e,f,g,h,i){var j +return b(19),c[0]=0,j=a(e,0,19,19,null,null,g,f,h,c,d),j==m?i.msg="oversubscribed dynamic bit lengths tree":(j==o||0===f[0])&&(i.msg="incomplete dynamic bit lengths tree",j=m),j},j.inflate_trees_dynamic=function(e,f,g,h,j,k,l,p,q){var r +return b(288),c[0]=0,r=a(g,0,e,257,x,y,k,h,p,c,d),r!=i||0===h[0]?(r==m?q.msg="oversubscribed literal/length tree":r!=n&&(q.msg="incomplete literal/length tree",r=m),r):(b(288),r=a(g,e,f,0,z,A,l,j,p,c,d),r!=i||0===j[0]&&e>257?(r==m?q.msg="oversubscribed distance tree":r==o?(q.msg="incomplete distance tree",r=m):r!=n&&(q.msg="empty distance tree with lengths",r=m),r):i)}}function c(){function a(a,b,c,d,e,f,g,h){var k,l,n,o,q,r,s,t,u,v,w,x,y,z,A,B +s=h.next_in_index,t=h.avail_in,q=g.bitb,r=g.bitk,u=g.write,v=ur;)t--,q|=(255&h.read_byte(s++))<>=l[B+1],r-=l[B+1],0!==(16&o)){for(o&=15,y=l[B+2]+(q&p[o]),q>>=o,r-=o;15>r;)t--,q|=(255&h.read_byte(s++))<>=l[B+1],r-=l[B+1],0!==(16&o)){for(o&=15;o>r;)t--,q|=(255&h.read_byte(s++))<>=o,r-=o,v-=y,u>=z)A=u-z,u-A>0&&2>u-A?(g.window[u++]=g.window[A++],g.window[u++]=g.window[A++],y-=2):(g.window.set(g.window.subarray(A,A+2),u),u+=2,A+=2,y-=2) +else{A=u-z +do A+=g.end +while(0>A) +if(o=g.end-A,y>o){if(y-=o,u-A>0&&o>u-A){do g.window[u++]=g.window[A++] +while(0!==--o)}else g.window.set(g.window.subarray(A,A+o),u),u+=o,A+=o,o=0 +A=0}}if(u-A>0&&y>u-A){do g.window[u++]=g.window[A++] +while(0!==--y)}else g.window.set(g.window.subarray(A,A+y),u),u+=y,A+=y,y=0 +break}if(0!==(64&o))return h.msg="invalid distance code",y=h.avail_in-t,y=y>r>>3?r>>3:y,t+=y,s-=y,r-=y<<3,g.bitb=q,g.bitk=r,h.avail_in=t,h.total_in+=s-h.next_in_index,h.next_in_index=s,g.write=u,m +k+=l[B+2],k+=q&p[o],B=3*(n+k),o=l[B]}break}if(0!==(64&o))return 0!==(32&o)?(y=h.avail_in-t,y=y>r>>3?r>>3:y,t+=y,s-=y,r-=y<<3,g.bitb=q,g.bitk=r,h.avail_in=t,h.total_in+=s-h.next_in_index,h.next_in_index=s,g.write=u,j):(h.msg="invalid literal/length code",y=h.avail_in-t,y=y>r>>3?r>>3:y,t+=y,s-=y,r-=y<<3,g.bitb=q,g.bitk=r,h.avail_in=t,h.total_in+=s-h.next_in_index,h.next_in_index=s,g.write=u,m) +if(k+=l[B+2],k+=q&p[o],B=3*(n+k),0===(o=l[B])){q>>=l[B+1],r-=l[B+1],g.window[u++]=l[B+2],v-- +break}}else q>>=l[B+1],r-=l[B+1],g.window[u++]=l[B+2],v--}while(v>=258&&t>=10) +return y=h.avail_in-t,y=y>r>>3?r>>3:y,t+=y,s-=y,r-=y<<3,g.bitb=q,g.bitk=r,h.avail_in=t,h.total_in+=s-h.next_in_index,h.next_in_index=s,g.write=u,i}var b,c,d,e,f=this,g=0,h=0,k=0,n=0,o=0,q=0,r=0,s=0,t=0,u=0 +f.init=function(a,f,g,h,i,j){b=C,r=a,s=f,d=g,t=h,e=i,u=j,c=null},f.proc=function(f,v,w){var x,y,z,A,B,M,N,O=0,P=0,Q=0 +for(Q=v.next_in_index,A=v.avail_in,O=f.bitb,P=f.bitk,B=f.write,M=B=258&&A>=10&&(f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,w=a(r,s,d,t,e,u,f,v),Q=v.next_in_index,A=v.avail_in,O=f.bitb,P=f.bitk,B=f.write,M=BP;){if(0===A)return f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,f.inflate_flush(v,w) +w=i,A--,O|=(255&v.read_byte(Q++))<>>=c[y+1],P-=c[y+1],z=c[y],0===z){n=c[y+2],b=I +break}if(0!==(16&z)){o=15&z,g=c[y+2],b=E +break}if(0===(64&z)){k=z,h=y/3+c[y+2] +break}if(0!==(32&z)){b=J +break}return b=L,v.msg="invalid literal/length code",w=m,f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,f.inflate_flush(v,w) +case E:for(x=o;x>P;){if(0===A)return f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,f.inflate_flush(v,w) +w=i,A--,O|=(255&v.read_byte(Q++))<>=x,P-=x,k=s,c=e,h=u,b=F +case F:for(x=k;x>P;){if(0===A)return f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,f.inflate_flush(v,w) +w=i,A--,O|=(255&v.read_byte(Q++))<>=c[y+1],P-=c[y+1],z=c[y],0!==(16&z)){o=15&z,q=c[y+2],b=G +break}if(0===(64&z)){k=z,h=y/3+c[y+2] +break}return b=L,v.msg="invalid distance code",w=m,f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,f.inflate_flush(v,w) +case G:for(x=o;x>P;){if(0===A)return f.bitb=O,f.bitk=P,v.avail_in=A,v.total_in+=Q-v.next_in_index,v.next_in_index=Q,f.write=B,f.inflate_flush(v,w) +w=i,A--,O|=(255&v.read_byte(Q++))<>=x,P-=x,b=H +case H:for(N=B-q;0>N;)N+=f.end +for(;0!==g;){if(0===M&&(B==f.end&&0!==f.read&&(B=0,M=B7&&(P-=8,A++,Q--),f.write=B,w=f.inflate_flush(v,w),B=f.write,M=Ba.avail_out&&(c=a.avail_out),0!==c&&b==o&&(b=i),a.avail_out-=c,a.total_out+=c,a.next_out.set(f.window.subarray(e,e+c),d),d+=c,e+=c,e==f.end&&(e=0,f.write==f.end&&(f.write=0),c=f.write-e,c>a.avail_out&&(c=a.avail_out),0!==c&&b==o&&(b=i),a.avail_out-=c,a.total_out+=c,a.next_out.set(f.window.subarray(e,e+c),d),d+=c,e+=c),a.next_out_index=d,f.read=e,b},f.proc=function(a,c){var d,o,q,w,y,z,A,B +for(w=a.next_in_index,y=a.avail_in,o=f.bitb,q=f.bitk,z=f.write,A=zq;){if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c) +c=i,y--,o|=(255&a.read_byte(w++))<>>1){case 0:o>>>=3,q-=3,d=7&q,o>>>=d,q-=d,g=O +break +case 1:var C=[],D=[],E=[[]],F=[[]] +b.inflate_trees_fixed(C,D,E,F),t.init(C[0],D[0],E[0],0,F[0],0),o>>>=3,q-=3,g=T +break +case 2:o>>>=3,q-=3,g=Q +break +case 3:return o>>>=3,q-=3,g=W,a.msg="invalid block type",c=m,f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c)}break +case O:for(;32>q;){if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c) +c=i,y--,o|=(255&a.read_byte(w++))<>>16&65535)!=(65535&o))return g=W,a.msg="invalid stored block lengths",c=m,f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c) +h=65535&o,o=q=0,g=0!==h?P:0!==u?U:N +break +case P:if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c) +if(0===A&&(z==f.end&&0!==f.read&&(z=0,A=zy&&(d=y),d>A&&(d=A),f.window.set(a.read_buf(w,d),z),w+=d,y-=d,z+=d,A-=d,0!==(h-=d))break +g=0!==u?U:N +break +case Q:for(;14>q;){if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c) +c=i,y--,o|=(255&a.read_byte(w++))<29||(d>>5&31)>29)return g=W,a.msg="too many length or distance symbols",c=m,f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c) +if(d=258+(31&d)+(d>>5&31),!e||e.lengthB;B++)e[B]=0 +o>>>=14,q-=14,n=0,g=R +case R:for(;4+(k>>>10)>n;){for(;3>q;){if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c) +c=i,y--,o|=(255&a.read_byte(w++))<>>=3,q-=3}for(;19>n;)e[M[n++]]=0 +if(r[0]=7,d=x.inflate_trees_bits(e,r,s,v,a),d!=i)return c=d,c==m&&(e=null,g=W),f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c) +n=0,g=S +case S:for(;;){if(d=k,!(258+(31&d)+(d>>5&31)>n))break +var G,H +for(d=r[0];d>q;){if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c) +c=i,y--,o|=(255&a.read_byte(w++))<H)o>>>=d,q-=d,e[n++]=H +else{for(B=18==H?7:H-14,G=18==H?11:3;d+B>q;){if(0===y)return f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c) +c=i,y--,o|=(255&a.read_byte(w++))<>>=d,q-=d,G+=o&p[B],o>>>=B,q-=B,B=n,d=k,B+G>258+(31&d)+(d>>5&31)||16==H&&1>B)return e=null,g=W,a.msg="invalid bit length repeat",c=m,f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c) +H=16==H?e[B-1]:0 +do e[B++]=H +while(0!==--G) +n=B}}s[0]=-1 +var I=[],J=[],K=[],L=[] +if(I[0]=9,J[0]=6,d=k,d=x.inflate_trees_dynamic(257+(31&d),1+(d>>5&31),e,I,J,K,L,v,a),d!=i)return d==m&&(e=null,g=W),c=d,f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,f.inflate_flush(a,c) +t.init(I[0],J[0],v,K[0],v,L[0]),g=T +case T:if(f.bitb=o,f.bitk=q,a.avail_in=y,a.total_in+=w-a.next_in_index,a.next_in_index=w,f.write=z,(c=t.proc(f,a,c))!=j)return f.inflate_flush(a,c) +if(c=i,t.free(a),w=a.next_in_index,y=a.avail_in,o=f.bitb,q=f.bitk,z=f.write,A=ze||e>15?(b.inflateEnd(c),l):(b.wbits=e,c.istate.blocks=new d(c,1<>4)+8>a.istate.wbits){a.istate.mode=ga,a.msg="invalid window size",a.istate.marker=5 +break}a.istate.mode=$ +case $:if(0===a.avail_in)return c +if(c=b,a.avail_in--,a.total_in++,d=255&a.read_byte(a.next_in_index++),((a.istate.method<<8)+d)%31!==0){a.istate.mode=ga,a.msg="incorrect header check",a.istate.marker=5 +break}if(0===(d&X)){a.istate.mode=ea +break}a.istate.mode=_ +case _:if(0===a.avail_in)return c +c=b,a.avail_in--,a.total_in++,a.istate.need=(255&a.read_byte(a.next_in_index++))<<24&4278190080,a.istate.mode=aa +case aa:if(0===a.avail_in)return c +c=b,a.avail_in--,a.total_in++,a.istate.need+=(255&a.read_byte(a.next_in_index++))<<16&16711680,a.istate.mode=ba +case ba:if(0===a.avail_in)return c +c=b,a.avail_in--,a.total_in++,a.istate.need+=(255&a.read_byte(a.next_in_index++))<<8&65280,a.istate.mode=ca +case ca:return 0===a.avail_in?c:(c=b,a.avail_in--,a.total_in++,a.istate.need+=255&a.read_byte(a.next_in_index++),a.istate.mode=da,k) +case da:return a.istate.mode=ga,a.msg="need dictionary",a.istate.marker=0,l +case ea:if(c=a.istate.blocks.proc(a,c),c==m){a.istate.mode=ga,a.istate.marker=0 +break}if(c==i&&(c=b),c!=j)return c +c=b,a.istate.blocks.reset(a,a.istate.was),a.istate.mode=fa +case fa:return j +case ga:return m +default:return l}},b.inflateSetDictionary=function(a,b,c){var d=0,e=c +return a&&a.istate&&a.istate.mode==da?(e>=1<e;)b.read_byte(d)==ha[e]?e++:e=0!==b.read_byte(d)?0:4-e,d++,c-- +return b.total_in+=d-b.next_in_index,b.next_in_index=d,b.avail_in=c,b.istate.marker=e,4!=e?m:(f=b.total_in,g=b.total_out,a(b),b.total_in=f,b.total_out=g,b.istate.mode=ea,i)},b.inflateSyncPoint=function(a){return a&&a.istate&&a.istate.blocks?a.istate.blocks.sync_point():l}}function f(){}function g(){var a=this,b=new f,c=512,d=r,e=new Uint8Array(c),g=!1 +b.inflateInit(),b.next_out=e,a.append=function(a,f){var h,k,l=[],m=0,n=0,p=0 +if(0!==a.length){b.next_in_index=0,b.next_in=a,b.avail_in=a.length +do{if(b.next_out_index=0,b.avail_out=c,0!==b.avail_in||g||(b.next_in_index=0,g=!0),h=b.inflate(d),g&&h==o)return-1 +if(h!=i&&h!=j)throw"inflating: "+b.msg +if((g||h==j)&&b.avail_in==a.length)return-1 +b.next_out_index&&(b.next_out_index==c?l.push(new Uint8Array(e)):l.push(new Uint8Array(e.subarray(0,b.next_out_index)))),p+=b.next_out_index,f&&b.next_in_index>0&&b.next_in_index!=m&&(f(b.next_in_index),m=b.next_in_index)}while(b.avail_in>0||0===b.avail_out) +return k=new Uint8Array(p),l.forEach(function(a){k.set(a,n),n+=a.length}),k}},a.flush=function(){b.inflateEnd()}}var h=15,i=0,j=1,k=2,l=-2,m=-3,n=-4,o=-5,p=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],q=1440,r=0,s=4,t=9,u=5,v=[96,7,256,0,8,80,0,8,16,84,8,115,82,7,31,0,8,112,0,8,48,0,9,192,80,7,10,0,8,96,0,8,32,0,9,160,0,8,0,0,8,128,0,8,64,0,9,224,80,7,6,0,8,88,0,8,24,0,9,144,83,7,59,0,8,120,0,8,56,0,9,208,81,7,17,0,8,104,0,8,40,0,9,176,0,8,8,0,8,136,0,8,72,0,9,240,80,7,4,0,8,84,0,8,20,85,8,227,83,7,43,0,8,116,0,8,52,0,9,200,81,7,13,0,8,100,0,8,36,0,9,168,0,8,4,0,8,132,0,8,68,0,9,232,80,7,8,0,8,92,0,8,28,0,9,152,84,7,83,0,8,124,0,8,60,0,9,216,82,7,23,0,8,108,0,8,44,0,9,184,0,8,12,0,8,140,0,8,76,0,9,248,80,7,3,0,8,82,0,8,18,85,8,163,83,7,35,0,8,114,0,8,50,0,9,196,81,7,11,0,8,98,0,8,34,0,9,164,0,8,2,0,8,130,0,8,66,0,9,228,80,7,7,0,8,90,0,8,26,0,9,148,84,7,67,0,8,122,0,8,58,0,9,212,82,7,19,0,8,106,0,8,42,0,9,180,0,8,10,0,8,138,0,8,74,0,9,244,80,7,5,0,8,86,0,8,22,192,8,0,83,7,51,0,8,118,0,8,54,0,9,204,81,7,15,0,8,102,0,8,38,0,9,172,0,8,6,0,8,134,0,8,70,0,9,236,80,7,9,0,8,94,0,8,30,0,9,156,84,7,99,0,8,126,0,8,62,0,9,220,82,7,27,0,8,110,0,8,46,0,9,188,0,8,14,0,8,142,0,8,78,0,9,252,96,7,256,0,8,81,0,8,17,85,8,131,82,7,31,0,8,113,0,8,49,0,9,194,80,7,10,0,8,97,0,8,33,0,9,162,0,8,1,0,8,129,0,8,65,0,9,226,80,7,6,0,8,89,0,8,25,0,9,146,83,7,59,0,8,121,0,8,57,0,9,210,81,7,17,0,8,105,0,8,41,0,9,178,0,8,9,0,8,137,0,8,73,0,9,242,80,7,4,0,8,85,0,8,21,80,8,258,83,7,43,0,8,117,0,8,53,0,9,202,81,7,13,0,8,101,0,8,37,0,9,170,0,8,5,0,8,133,0,8,69,0,9,234,80,7,8,0,8,93,0,8,29,0,9,154,84,7,83,0,8,125,0,8,61,0,9,218,82,7,23,0,8,109,0,8,45,0,9,186,0,8,13,0,8,141,0,8,77,0,9,250,80,7,3,0,8,83,0,8,19,85,8,195,83,7,35,0,8,115,0,8,51,0,9,198,81,7,11,0,8,99,0,8,35,0,9,166,0,8,3,0,8,131,0,8,67,0,9,230,80,7,7,0,8,91,0,8,27,0,9,150,84,7,67,0,8,123,0,8,59,0,9,214,82,7,19,0,8,107,0,8,43,0,9,182,0,8,11,0,8,139,0,8,75,0,9,246,80,7,5,0,8,87,0,8,23,192,8,0,83,7,51,0,8,119,0,8,55,0,9,206,81,7,15,0,8,103,0,8,39,0,9,174,0,8,7,0,8,135,0,8,71,0,9,238,80,7,9,0,8,95,0,8,31,0,9,158,84,7,99,0,8,127,0,8,63,0,9,222,82,7,27,0,8,111,0,8,47,0,9,190,0,8,15,0,8,143,0,8,79,0,9,254,96,7,256,0,8,80,0,8,16,84,8,115,82,7,31,0,8,112,0,8,48,0,9,193,80,7,10,0,8,96,0,8,32,0,9,161,0,8,0,0,8,128,0,8,64,0,9,225,80,7,6,0,8,88,0,8,24,0,9,145,83,7,59,0,8,120,0,8,56,0,9,209,81,7,17,0,8,104,0,8,40,0,9,177,0,8,8,0,8,136,0,8,72,0,9,241,80,7,4,0,8,84,0,8,20,85,8,227,83,7,43,0,8,116,0,8,52,0,9,201,81,7,13,0,8,100,0,8,36,0,9,169,0,8,4,0,8,132,0,8,68,0,9,233,80,7,8,0,8,92,0,8,28,0,9,153,84,7,83,0,8,124,0,8,60,0,9,217,82,7,23,0,8,108,0,8,44,0,9,185,0,8,12,0,8,140,0,8,76,0,9,249,80,7,3,0,8,82,0,8,18,85,8,163,83,7,35,0,8,114,0,8,50,0,9,197,81,7,11,0,8,98,0,8,34,0,9,165,0,8,2,0,8,130,0,8,66,0,9,229,80,7,7,0,8,90,0,8,26,0,9,149,84,7,67,0,8,122,0,8,58,0,9,213,82,7,19,0,8,106,0,8,42,0,9,181,0,8,10,0,8,138,0,8,74,0,9,245,80,7,5,0,8,86,0,8,22,192,8,0,83,7,51,0,8,118,0,8,54,0,9,205,81,7,15,0,8,102,0,8,38,0,9,173,0,8,6,0,8,134,0,8,70,0,9,237,80,7,9,0,8,94,0,8,30,0,9,157,84,7,99,0,8,126,0,8,62,0,9,221,82,7,27,0,8,110,0,8,46,0,9,189,0,8,14,0,8,142,0,8,78,0,9,253,96,7,256,0,8,81,0,8,17,85,8,131,82,7,31,0,8,113,0,8,49,0,9,195,80,7,10,0,8,97,0,8,33,0,9,163,0,8,1,0,8,129,0,8,65,0,9,227,80,7,6,0,8,89,0,8,25,0,9,147,83,7,59,0,8,121,0,8,57,0,9,211,81,7,17,0,8,105,0,8,41,0,9,179,0,8,9,0,8,137,0,8,73,0,9,243,80,7,4,0,8,85,0,8,21,80,8,258,83,7,43,0,8,117,0,8,53,0,9,203,81,7,13,0,8,101,0,8,37,0,9,171,0,8,5,0,8,133,0,8,69,0,9,235,80,7,8,0,8,93,0,8,29,0,9,155,84,7,83,0,8,125,0,8,61,0,9,219,82,7,23,0,8,109,0,8,45,0,9,187,0,8,13,0,8,141,0,8,77,0,9,251,80,7,3,0,8,83,0,8,19,85,8,195,83,7,35,0,8,115,0,8,51,0,9,199,81,7,11,0,8,99,0,8,35,0,9,167,0,8,3,0,8,131,0,8,67,0,9,231,80,7,7,0,8,91,0,8,27,0,9,151,84,7,67,0,8,123,0,8,59,0,9,215,82,7,19,0,8,107,0,8,43,0,9,183,0,8,11,0,8,139,0,8,75,0,9,247,80,7,5,0,8,87,0,8,23,192,8,0,83,7,51,0,8,119,0,8,55,0,9,207,81,7,15,0,8,103,0,8,39,0,9,175,0,8,7,0,8,135,0,8,71,0,9,239,80,7,9,0,8,95,0,8,31,0,9,159,84,7,99,0,8,127,0,8,63,0,9,223,82,7,27,0,8,111,0,8,47,0,9,191,0,8,15,0,8,143,0,8,79,0,9,255],w=[80,5,1,87,5,257,83,5,17,91,5,4097,81,5,5,89,5,1025,85,5,65,93,5,16385,80,5,3,88,5,513,84,5,33,92,5,8193,82,5,9,90,5,2049,86,5,129,192,5,24577,80,5,2,87,5,385,83,5,25,91,5,6145,81,5,7,89,5,1537,85,5,97,93,5,24577,80,5,4,88,5,769,84,5,49,92,5,12289,82,5,13,90,5,3073,86,5,193,192,5,24577],x=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],y=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,112,112],z=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],A=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],B=15 +b.inflate_trees_fixed=function(a,b,c,d){return a[0]=t,b[0]=u,c[0]=v,d[0]=w,i} +var C=0,D=1,E=2,F=3,G=4,H=5,I=6,J=7,K=8,L=9,M=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],N=0,O=1,P=2,Q=3,R=4,S=5,T=6,U=7,V=8,W=9,X=32,Y=8,Z=0,$=1,_=2,aa=3,ba=4,ca=5,da=6,ea=7,fa=12,ga=13,ha=[0,0,255,255] +f.prototype={inflateInit:function(a){var b=this +return b.istate=new e,a||(a=h),b.istate.inflateInit(b,a)},inflate:function(a){var b=this +return b.istate?b.istate.inflate(b,a):l},inflateEnd:function(){var a=this +if(!a.istate)return l +var b=a.istate.inflateEnd(a) +return a.istate=null,b},inflateSync:function(){var a=this +return a.istate?a.istate.inflateSync(a):l},inflateSetDictionary:function(a,b){var c=this +return c.istate?c.istate.inflateSetDictionary(c,a,b):l},read_byte:function(a){var b=this +return b.next_in.subarray(a,a+1)[0]},read_buf:function(a,b){var c=this +return c.next_in.subarray(a,a+b)}} +var ia +a.zip?a.zip.Inflater=g:(ia=new g,a.addEventListener("message",function(b){var c=b.data +c.append&&a.postMessage({onappend:!0,data:ia.append(c.data,function(b){a.postMessage({progress:!0,current:b})})}),c.flush&&(ia.flush(),a.postMessage({onflush:!0}))},!1))},O.esri.TPK.___test=O.esri.TPK.inflate.toString(),O.esri.TPK.___blobURL=URL.createObjectURL(new Blob(["(",O.esri.TPK.___test,")(this)"],{type:"application/javascript"})),O.esri.zip.workerScriptsPath=O.esri.TPK.___blobURL,O.esri.TPK.X2JS=function(a){"use strict" +function b(){void 0===a.escapeMode&&(a.escapeMode=!0),a.attributePrefix=a.attributePrefix||"_",a.arrayAccessForm=a.arrayAccessForm||"none",a.emptyNodeForm=a.emptyNodeForm||"text",void 0===a.enableToStringFunc&&(a.enableToStringFunc=!0),a.arrayAccessFormPaths=a.arrayAccessFormPaths||[],void 0===a.skipEmptyTextNodesForObj&&(a.skipEmptyTextNodesForObj=!0),void 0===a.stripWhitespaces&&(a.stripWhitespaces=!0),a.datetimeAccessFormPaths=a.datetimeAccessFormPaths||[]}function c(){function a(a){var b=String(a) +return 1===b.length&&(b="0"+b),b}"function"!=typeof String.prototype.trim&&(String.prototype.trim=function(){return this.replace(/^\s+|^\n+|(\s|\n)+$/g,"")}),"function"!=typeof Date.prototype.toISOString&&(Date.prototype.toISOString=function(){return this.getUTCFullYear()+"-"+a(this.getUTCMonth()+1)+"-"+a(this.getUTCDate())+"T"+a(this.getUTCHours())+":"+a(this.getUTCMinutes())+":"+a(this.getUTCSeconds())+"."+String((this.getUTCMilliseconds()/1e3).toFixed(3)).slice(2,5)+"Z"})}function d(a){var b=a.localName +return null==b&&(b=a.baseName),(null==b||""==b)&&(b=a.nodeName),b}function e(a){return a.prefix}function f(a){return"string"==typeof a?a.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/"):a}function g(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(///g,"/")}function h(b,c,d){switch(a.arrayAccessForm){case"property":b[c]instanceof Array?b[c+"_asArray"]=b[c]:b[c+"_asArray"]=[b[c]]}if(!(b[c]instanceof Array)&&a.arrayAccessFormPaths.length>0){for(var e=0;e1&&c.setMilliseconds(d[1]),b[6]&&b[7]){var e=60*b[6]+Number(b[7]),f=/\d\d-\d\d:\d\d$/.test(a)?"-":"+" +e=0+("-"==f?-1*e:e),c.setMinutes(c.getMinutes()-e-c.getTimezoneOffset())}else-1!==a.indexOf("Z",a.length-1)&&(c=new Date(Date.UTC(c.getFullYear(),c.getMonth(),c.getDate(),c.getHours(),c.getMinutes(),c.getSeconds(),c.getMilliseconds()))) +return c}function j(b,c,d){if(a.datetimeAccessFormPaths.length>0){for(var e=d.split(".#")[0],f=0;f1&&null!=f.__text&&a.skipEmptyTextNodesForObj&&(a.stripWhitespaces&&""==f.__text||""==f.__text.trim())&&delete f.__text,delete f.__cnt,!a.enableToStringFunc||null==f.__text&&null==f.__cdata||(f.toString=function(){return(null!=this.__text?this.__text:"")+(null!=this.__cdata?this.__cdata:"")}),f}return b.nodeType==w.TEXT_NODE||b.nodeType==w.CDATA_SECTION_NODE?b.nodeValue:void 0}function l(b,c,d,e){var g="<"+(null!=b&&null!=b.__prefix?b.__prefix+":":"")+c +if(null!=d)for(var h=0;h":">"}function m(a,b){return""}function n(a,b){return-1!==a.indexOf(b,a.length-b.length)}function o(b,c){return"property"==a.arrayAccessForm&&n(c.toString(),"_asArray")||0==c.toString().indexOf(a.attributePrefix)||0==c.toString().indexOf("__")||b[c]instanceof Function?!0:!1}function p(a){var b=0 +if(a instanceof Object)for(var c in a)o(a,c)||b++ +return b}function q(b){var c=[] +if(b instanceof Object)for(var d in b)-1==d.toString().indexOf("__")&&0==d.toString().indexOf(a.attributePrefix)&&c.push(d) +return c}function r(b){var c="" +return null!=b.__cdata&&(c+=""),null!=b.__text&&(c+=a.escapeMode?f(b.__text):b.__text),c}function s(b){var c="" +return b instanceof Object?c+=r(b):null!=b&&(c+=a.escapeMode?f(b):b),c}function t(a,b,c){var d="" +if(0==a.length)d+=l(a,b,c,!0) +else for(var e=0;e0)for(var d in a)if(!o(a,d)){var e=a[d],f=q(e) +if(null==e||void 0==e)b+=l(e,d,f,!0) +else if(e instanceof Object)if(e instanceof Array)b+=t(e,d,f) +else if(e instanceof Date)b+=l(e,d,f,!1),b+=e.toISOString(),b+=m(e,d) +else{var g=p(e) +g>0||null!=e.__text||null!=e.__cdata?(b+=l(e,d,f,!1),b+=u(e),b+=m(e,d)):b+=l(e,d,f,!0)}else b+=l(e,d,f,!1),b+=s(e),b+=m(e,d)}return b+=s(a)}var v="1.1.5",a=a||{} +b(),c() +var w={ELEMENT_NODE:1,TEXT_NODE:3,CDATA_SECTION_NODE:4,COMMENT_NODE:8,DOCUMENT_NODE:9} +this.parseXmlString=function(a){var b=window.ActiveXObject||"ActiveXObject"in window +if(void 0===a)return null +var c +if(window.DOMParser){var d=new window.DOMParser,e=null +if(!b)try{e=d.parseFromString("INVALID","text/xml").childNodes[0].namespaceURI}catch(f){e=null}try{c=d.parseFromString(a,"text/xml"),null!=e&&c.getElementsByTagNameNS(e,"parsererror").length>0&&(c=null)}catch(f){c=null}}else 0==a.indexOf("")+2)),c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(a) +return c},this.asArray=function(a){return a instanceof Array?a:[a]},this.toXmlDateTime=function(a){return a instanceof Date?a.toISOString():"number"==typeof a?new Date(a).toISOString():null},this.asDateTime=function(a){return"string"==typeof a?i(a):a},this.xml2json=function(a){return k(a)},this.xml_str2json=function(a){var b=this.parseXmlString(a) +return null!=b?this.xml2json(b):null},this.json2xml_str=function(a){return u(a)},this.json2xml=function(a){var b=this.json2xml_str(a) +return this.parseXmlString(b)},this.getVersion=function(){return v}} diff --git a/dist/offline-tpk-src.js b/dist/offline-tpk-src.js index 14a139f6..199cf2bc 100644 --- a/dist/offline-tpk-src.js +++ b/dist/offline-tpk-src.js @@ -1,4 +1,4 @@ -/*! esri-offline-maps - v2.16.0 - 2015-10-29 +/*! esri-offline-maps - v3.0.0 - 2015-11-23 * Copyright (c) 2015 Environmental Systems Research Institute, Inc. * Apache License*/ /** @@ -147,7 +147,7 @@ define([ // 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; - console.log("URL length " + imgURL.length + ", image: " + imgURL); + //console.log("URL length " + imgURL.length + ", image: " + imgURL); this.emit(this.PROGRESS_EVENT,this.PROGRESS_END); return ""; /* this result goes nowhere, seriously */ @@ -204,7 +204,7 @@ define([ }, /** - * Reads a tile into tile database. Works with offlineTilesEnabler.js and OfflineTilesEnablerLayer.js + * Reads a tile into tile database. Works with OfflineTilesBasic.js and OfflineTilesAdvanced.js * saveToFile() functionality. * IMPORTANT! The tile must confirm to an object using the pattern shown in _storeTile(). * @param file diff --git a/doc/attachments.md b/doc/attachments.md index 7c2f3953..57495a12 100644 --- a/doc/attachments.md +++ b/doc/attachments.md @@ -15,14 +15,14 @@ You can either use the ArcGIS FeatureLayer API _(esri.layers.FeatureLayer)_ dire The only differences in your code are: -* create an offlineFeaturesManager enabled for attachment support. Make sure you initialize the attachments database: +* create an OfflineEditAdvanced instance that is enabled for attachment support. Make sure you initialize the attachments database: - var offlineFeaturesManager = new esri.OfflineFeaturesManager(); - offlineFeaturesManager.initAttachments(); + var offlineEdit = new O.esri.Edit.OfflineEditAdvanced(); + offlineEdit.initAttachments(); * extend your featureLayers with offline editing functionality: - offlineFeaturesManager.extend(featureLayer, function(success, error) + offlineEdit.extend(featureLayer, function(success, error) { console.log("layer extended", success? "success" : "failed"); }); @@ -30,14 +30,14 @@ The only differences in your code are: You can also modified the database's name and object store name. This functionality is typically used for advanced users that have a requirement to run multiple databases: - var offlineFeaturesManager = new esri.OfflineFeaturesManager(); - offlineFeaturesManager.ATTACHMENTS_DB_NAME = "attachment-store-two"; - offlineFeaturesManager.ATTACHMENTS_DB_OBJECTSTORE_NAME = "attachments-two"; + var offlineEdit = new O.esri.Edit.OfflineEditAdvanced(); + offlineEdit.ATTACHMENTS_DB_NAME = "attachment-store-two"; + offlineEdit.ATTACHMENTS_DB_OBJECTSTORE_NAME = "attachments-two"; - offlineFeaturesManager.initAttachments(); + offlineEdit.initAttachments(); ###Using the FeatureLayer API -The FeatureLayer API for handling attachments consists primarily of four methods. In general you should let `OfflineFeaturesManager` +The FeatureLayer API for handling attachments consists primarily of four methods. In general you should let `OfflineEditAdvanced` handle interactions with attachments and it's not recommended to interact with the attachments database directly. * `layer.queryAttachmentInfos(objectId,callback,errback)` [doc](https://developers.arcgis.com/javascript/jsapi/featurelayer.html#queryattachmentinfos) @@ -45,7 +45,7 @@ handle interactions with attachments and it's not recommended to interact with t * `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. * `layer.deleteAttachments(objectId, attachmentIds, callback, errback)` [doc](https://developers.arcgis.com/javascript/jsapi/featurelayer.html#deleteattachments) -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 `offlineFeaturesManager.goOnline()` +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()` ##Getting database usage 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: diff --git a/doc/howtouseeditlibrary.md b/doc/howtouseofmadvancedlibrary.md similarity index 74% rename from doc/howtouseeditlibrary.md rename to doc/howtouseofmadvancedlibrary.md index fcef3df9..4152a985 100644 --- a/doc/howtouseeditlibrary.md +++ b/doc/howtouseofmadvancedlibrary.md @@ -1,23 +1,23 @@ -How to use the edit library -=========================== +How to use the advanced edit library +==================================== -##`edit` library +##`OfflineEditAdvanced` library -The `edit` library allows a developer to extend a feature layer with offline editing support. You can combine this functionality with offline tiles. For a complete list of features consult the [OfflineFeaturesManager API doc](offlinefeaturesmanager.md). +This library allows a developer to extend a feature layer with intermittent and full offline editing support. You can combine this functionality with offline tiles. For a complete list of features consult the [OfflineEditAdvanced API doc](offlineeditadvanced.md). -**IMPORTANT:** Only use a single instance of OfflineFeaturesManager per application. With this single instance you can extend offline capabilities to multiple feature layers. This single instance contains all edits for all feature layers initialized via `offlineFeaturesManager.extend().` Multiple feature layers share a single database. The database maintains the relationship between each edit and its' respective feature layer via a UUID. +**IMPORTANT:** Only use a single instance of OfflineEditAdvanced per application. With this single instance you can extend offline capabilities to multiple feature layers. This single instance contains all edits for all feature layers initialized via `OfflineEditAdvanced.extend().` Multiple feature layers share a single database. The database maintains the relationship between each edit and its' respective feature layer via a UUID. -**Step 1** Include `offline.min.js`, `offline-tiles-basic-min.js` and `offline-edit-min.js` in your app's require contstructor. Be sure to include `ofline.mins.js` which is a 3rd party library for detecting if the browser is online or offline. +**Step 1** Include `offline.min.js`, `offline-tiles-basic-min.js` and `offline-edit-advanced-min.js` in your app's require contstructor. Be sure to include `ofline.mins.js` which is a 3rd party library for detecting if the browser is online or offline. -The pattern for how we include the tiles and edit library within the `require` statement is called generic script injection. Note that we do assign any of the editing or tile libraries an alias name. For example, we specified the mobile path "esri/map" and we gave it an alias called "Map." But, we did not do the equivalent for `offline-tiles-based-min.js` or `offline-edit-min.js`. +The pattern for how we include the tiles and edit library within the `require` statement is called generic script injection. Note that we do assign any of the editing or tile libraries an alias name. For example, we specified the mobile path "esri/map" and we gave it an alias called "Map." But, we did not do the equivalent for `offline-tiles-basic-min.js` or `offline-edit-advanced-min.js`. ```html - + + + - + Include a reference to IndexedDBShim for library to work on Safari 7.x. + May not be required for all Safari browsers. + --> + - - - + + + + + + diff --git a/samples/appcache-twofeatureslayer-noedit.html b/samples/appcache-twofeatureslayer-noedit.html new file mode 100644 index 00000000..7590456a --- /dev/null +++ b/samples/appcache-twofeatureslayer-noedit.html @@ -0,0 +1,724 @@ + + + + + + + + + + + AppCache Tiles and Features + + + + + + + + + + + + + + + + + + + + + + + +
      +
      +
      +
      + + +
      +
      +
      + + +
      +
      +
      +
      +
      +
      +
      +
      + + + + + + + + + \ No newline at end of file diff --git a/samples/attachments-editor-secure.html b/samples/attachments-editor-secure.html index 2c6f3cd3..a976a1e5 100644 --- a/samples/attachments-editor-secure.html +++ b/samples/attachments-editor-secure.html @@ -19,7 +19,7 @@ - + - - - + + + - - + + + - - + + +
      @@ -135,10 +124,8 @@ "dojo/_base/array", "dojo/parser", "dojo/keys", "dojo/dom", "dojo/on", "dojo/dom-construct", "dojo/dom-class", "esri/domUtils", - "esri/graphic", - "dijit/layout/BorderContainer", "dijit/layout/ContentPane", - "../dist/offline-edit-src.js", + "../dist/offline-edit-basic-src.js", "dojo/domReady!" ], function( Map, GeometryService, Edit, @@ -148,7 +135,7 @@ esriConfig, jsapiBundle, Deferred, all, arrayUtils, parser, keys, - dom, on, domConstruct, domClass, domUtils,Graphic + dom, on, domConstruct, domClass, domUtils ) { var editor; @@ -161,13 +148,13 @@ on(dom.byId('go-offline-btn'),'click', goOffline); on(dom.byId('go-online-btn'),'click', goOnline); on(dom.byId('refresh-feature-layers-btn'),'click', refreshFeatureLayers); - var offlineFeaturesManager = new O.esri.Edit.OfflineFeaturesManager(); + var offlineEdit = new O.esri.Edit.OfflineEditBasic(); // IMPORTANT!!! // A proxy page may be required to upload attachments. // If you are using a CORS enabled server you may be ablew to set the proxyPath to null. // Refer to "Using the Proxy Page" for more information: https://developers.arcgis.com/en/javascript/jshelp/ags_proxy.html - offlineFeaturesManager.proxyPath = null; + offlineEdit.proxyPath = null; map = new Map("map", { basemap: "satellite", @@ -260,7 +247,7 @@ var layer = result.layer; offlineInitializedLayers.push(layer); - offlineFeaturesManager.extend(layer,function(success,error){ + offlineEdit.extend(layer,function(success,error){ if(success){ deferred.resolve(true); } @@ -290,16 +277,15 @@ // Things to do when all the promises complete function resolveOfflinePromises(){ - offlineFeaturesManager.on(offlineFeaturesManager.events.EDITS_ENQUEUED, updateStatus); - offlineFeaturesManager.on(offlineFeaturesManager.events.ALL_EDITS_SENT, updateStatusAllEditsSent); - offlineFeaturesManager.on(offlineFeaturesManager.events.EDITS_SENT_ERROR, handleEditsSentError); + offlineEdit.on(offlineEdit.events.EDITS_ENQUEUED, updateStatus); + offlineEdit.on(offlineEdit.events.EDITS_SENT, updateStatusAllEditsSent); offlineInitializedLayers[0].on("edits-complete", handleEditsComplete); offlineInitializedLayers[1].on("edits-complete", handleEditsComplete); offlineInitializedLayers[2].on("edits-complete", handleEditsComplete); // handle errors that happen while storing offline edits - offlineFeaturesManager.on(offlineFeaturesManager.events.EDITS_ENQUEUED_ERROR, function(errors) + offlineEdit.on(offlineEdit.events.EDITS_ENQUEUED_ERROR, function(errors) { if( errors.length ) { @@ -442,7 +428,7 @@ function goOnline() { domUtils.show(editor.progressBar.domNode); - offlineFeaturesManager.goOnline(function() + offlineEdit.goOnline(function() { domUtils.hide(editor.progressBar.domNode); updateConnectivityIndicator(); @@ -452,7 +438,7 @@ function goOffline() { - offlineFeaturesManager.goOffline(); + offlineEdit.goOffline(); updateConnectivityIndicator(); } @@ -460,17 +446,17 @@ { var node = dom.byId('connectivityIndicator'); domClass.remove(node, "online offline reconnecting"); - switch( offlineFeaturesManager.getOnlineStatus() ) + switch( offlineEdit.getOnlineStatus() ) { - case offlineFeaturesManager.OFFLINE: + case offlineEdit.OFFLINE: node.innerHTML = " offline"; domClass.add(node, "offline"); break; - case offlineFeaturesManager.ONLINE: + case offlineEdit.ONLINE: node.innerHTML = " online"; domClass.add(node, "online"); break; - case offlineFeaturesManager.RECONNECTING: + case offlineEdit.RECONNECTING: node.innerHTML = " reconnecting"; domClass.add(node, "reconnecting"); break; diff --git a/samples/package.json b/samples/package.json index 1d1be34d..a120c79c 100644 --- a/samples/package.json +++ b/samples/package.json @@ -9,7 +9,7 @@ "appHomePage": "appcache-tiles.html", "optimizedApiURL": "../samples/jsolib", "arcGISBaseURL": "http://js.arcgis.com/3.14", - "version": "2.16.0", + "version": "3.0.0", "private": true, "description": "manifest generator project", "repository": { @@ -24,6 +24,6 @@ "dependencies": {}, "devDependencies": { "grunt": "~0.4.5", - "grunt-manifest": "^0.4.0" + "grunt-manifest": "^0.4.4" } } diff --git a/samples/simple-edit.html b/samples/simple-edit.html new file mode 100644 index 00000000..0f75a5b4 --- /dev/null +++ b/samples/simple-edit.html @@ -0,0 +1,127 @@ + + + + + + + Update Fire Perimeter + + + + + + + + + + +
      + +
      +
      + + + \ No newline at end of file diff --git a/samples/tiles-indexed-db.html b/samples/simple-tiles.html similarity index 96% rename from samples/tiles-indexed-db.html rename to samples/simple-tiles.html index e9feefe5..dbda2a60 100644 --- a/samples/tiles-indexed-db.html +++ b/samples/simple-tiles.html @@ -7,12 +7,12 @@ - + - + - + - - + + - + diff --git a/test/SpecRunner.attachmentsStore.html b/test/SpecRunner.attachmentsStore.html index 80ccd8d1..1fcaa84d 100644 --- a/test/SpecRunner.attachmentsStore.html +++ b/test/SpecRunner.attachmentsStore.html @@ -20,6 +20,7 @@ + @@ -34,7 +35,7 @@ "esri/SpatialReference","esri/geometry", "dojo/dom", "dojo/on", "dojo/query", "dojo/dom-construct", - "../dist/offline-edit-src.js", + "../dist/offline-edit-advanced-src.js", "dojo/domReady!"], function(Map, GraphicsLayer, Graphic, SimpleFillSymbol, SimpleMarkerSymbol, SimpleLineSymbol, diff --git a/test/SpecRunner.editsStore.html b/test/SpecRunner.editsStore.html index e8bdcf06..61b019d0 100644 --- a/test/SpecRunner.editsStore.html +++ b/test/SpecRunner.editsStore.html @@ -20,6 +20,7 @@ + @@ -36,7 +37,7 @@ "esri/SpatialReference","esri/geometry", "dojo/dom", "dojo/on", "dojo/query", "dojo/dom-construct", - "../dist/offline-edit-src.js", + "../dist/offline-edit-advanced-src.js", "dojo/domReady!"], function(Map, GraphicsLayer, Graphic, SimpleFillSymbol, SimpleMarkerSymbol, SimpleLineSymbol, diff --git a/test/SpecRunner.offlineAttachments.html b/test/SpecRunner.offlineAttachments.html index ce3ba27d..00a89d3b 100644 --- a/test/SpecRunner.offlineAttachments.html +++ b/test/SpecRunner.offlineAttachments.html @@ -2,7 +2,7 @@ "http://www.w3.org/TR/html4/loose.dtd"> - Jasmine Spec Runner - offlineFeaturesManager + Jasmine Spec Runner - Offline Attachments @@ -22,6 +22,7 @@ + @@ -31,7 +32,7 @@ var g_map; var g_featureLayers = []; var g_featureLayer = null; - var g_offlineFeaturesManager; + var g_offlineEdit; var g_modules = {}; var g_editsStore; var g_formNode, g_formData, g_formData2, g_formNode2; @@ -41,7 +42,7 @@ "esri/layers/FeatureLayer", "esri/geometry", "esri/request", "dojo/dom", "dojo/on", "dojo/query", "dojo/dom-construct", - "../dist/offline-edit-src.js", + "../dist/offline-edit-advanced-src.js", "dojo/domReady!"], function(Map, GraphicsLayer, Graphic, @@ -51,12 +52,12 @@ { g_modules.esriRequest = esriRequest; g_modules.Graphic = Graphic; - g_offlineFeaturesManager = new O.esri.Edit.OfflineFeaturesManager(); - g_offlineFeaturesManager.DB_UID = "OBJECTID"; + g_offlineEdit = new O.esri.Edit.OfflineEditAdvanced(); + g_offlineEdit.DB_UID = "OBJECTID"; g_editsStore = new O.esri.Edit.EditStore(); - g_offlineFeaturesManager.initAttachments(function(success) + g_offlineEdit.initAttachments(function(success) { console.log("attachments inited", success); }); @@ -91,7 +92,7 @@ function test() { - g_offlineFeaturesManager.extend(g_featureLayer,function(success,message){ + g_offlineEdit.extend(g_featureLayer,function(success,message){ if(!success){ alert("There was a problem extending the layer: " + layer); } @@ -147,7 +148,7 @@ files.push(file); - // Fake a form node for our custom parser in offlineFeaturesManager.js + // Fake a form node for our custom parser in OfflineEditAdvanced.js g_formNode = { elements:[ {type:"file", diff --git a/test/SpecRunner.offlineFeaturesManager.TokenBased.html b/test/SpecRunner.offlineEditAdvanced.TokenBased.html similarity index 83% rename from test/SpecRunner.offlineFeaturesManager.TokenBased.html rename to test/SpecRunner.offlineEditAdvanced.TokenBased.html index 270e5498..14e84457 100644 --- a/test/SpecRunner.offlineFeaturesManager.TokenBased.html +++ b/test/SpecRunner.offlineEditAdvanced.TokenBased.html @@ -2,7 +2,7 @@ "https://www.w3.org/TR/html4/loose.dtd"> - Jasmine Spec Runner - offlineFeaturesManager + Jasmine Spec Runner - OfflineEditAdvanced @@ -22,16 +22,17 @@ + - + + - + + - + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/SpecRunner.offlineTilesEnablerLayer.TokenBased.html b/test/SpecRunner.offlineTilesAdvanced.TokenBased.html similarity index 95% rename from test/SpecRunner.offlineTilesEnablerLayer.TokenBased.html rename to test/SpecRunner.offlineTilesAdvanced.TokenBased.html index 590b2b92..a15b3b83 100644 --- a/test/SpecRunner.offlineTilesEnablerLayer.TokenBased.html +++ b/test/SpecRunner.offlineTilesAdvanced.TokenBased.html @@ -15,7 +15,7 @@ - + - + - +