Getting Started

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

Step 1: Fork or clone offline-editor-js

Here are the important directories to know:

  • \dist - concatenated library source and minified library files.
  • \samples - examples that demonstrate the library's functionality.
  • \vendor - contains IndexedDBShim and offline.js libraries

Step 2: 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>Simple Map</title>
    <link rel="stylesheet" href="http://js.arcgis.com/3.10/js/esri/css/esri.css">
    <style>
        html, body, #map {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }
        body {
            background-color: #000000;
            overflow: hidden;
            font-family: "Trebuchet MS";
        }
    </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.10/"></script>
</head>

<body>
    <div id="map"></div>

    <script>
        var map;

        // Make sure to reference the tiles library within the require statement!
        require(["esri/map","../dist/offline-tiles-advanced-min.js", "dojo/domReady!"], function(Map) {
            map = new Map("map", {
                basemap: "topo",
                center: [-122.45, 37.75], // longitude, latitude
                zoom: 13
            });
        });
    </script>
</body>
</html>

                        
                    
NOTE: Replace paths with your references.

Step 3: 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>Simple Map</title>
    <link rel="stylesheet" href="http://js.arcgis.com/3.10/js/esri/css/esri.css">
    <style>
        html, body, #map {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }
        body {
            background-color: #000000;
            overflow: hidden;
            font-family: "Trebuchet MS";
        }
    </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.10/"></script>
</head>

<body>
    <div id="map"></div>

    <script>
        var map;

        // Make sure to reference the offline tiles library within the require statement!
        require(["esri/map","../dist/offline-tiles-advanced-min.js", "dojo/domReady!"], function(Map) {

            // Check if browser state is online or offline
            Offline.check();
            Offline.on('up down', updateState );

            // Initialize Esri.Map
            map = new Map("map", {
                //basemap: "topo", // comment out this basemap!
                center: [-122.45, 37.75], // longitude, latitude
                zoom: 13
            });

            // Now we initialize a topo tiled basemap service to be offline-enabled.
            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 tiles database
            function updateState(){
                if(Offline.state === 'up'){
                    if(typeof tileLayer != "undefined") tileLayer.goOnline();
                }
                else{
                    if(typeof tileLayer != "undefined") tileLayer.goOffline();
                }
            }

        });
    </script>
</body>
</html>

                        
                    
NOTE: Replace paths with your references.

Step 4: 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>Simple Map</title>
    <link rel="stylesheet" href="http://js.arcgis.com/3.10/js/esri/css/esri.css">
    <style>
        html, body, #map {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }
        body {
            background-color: #000000;
            overflow: hidden;
            font-family: "Trebuchet MS";
        }
    </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.10/"></script>
</head>

<body>

    <button class="basic-btn" id="btn-get-tiles">1. Download Tiles</button>
    <button class="basic-btn" id="btn-online-offline">2. Go Offline</button>
    <button class="basic-btn" id="btn-pan-left">3. Pan left</button>

    <div id="map"></div>

    <script>
        var map;

        // Make sure to reference the offline tiles library within the require statement!
        require(["esri/map","dojo/on","../dist/offline-tiles-advanced-min.js", "dojo/domReady!"],
        function(Map,on){

            // Check if browser state is online or offline
            Offline.check();
            Offline.on('up down', updateState );

            // For cancelling the download of tiles
            var _wantToCancel;

            // 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");

            on(btnGetTiles,"click",downloadTiles);
            on(btnOnlineOffline,"click",goOnlineOffline);
            on(btnPanLeft,"click",panLeft);

            // Initialize Esri.Map
            map = new Map("map", {
                //basemap: "topo", // comment out this basemap!
                center: [-122.45, 37.75], // longitude, latitude
                zoom: 13
            });

            // Now we initialize a topo tiled basemap service to be offline-enabled.
            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);

            // Set the min and max zoom levels for when retrieving tiles
            // This helps manage the amount of database space used.
            map.on("load",function(evt){
                tileLayer.getMaxZoom(function(result){
                    mMaxZoom = result;
                });
                tileLayer.getMinZoom(function(result){
                    mMinZoom = result;
                });
            })

            // Add our offline tile layer to the map instead of using the default basemap!
            map.addLayer(tileLayer);

            function downloadTiles(){

                // First we need to empty the database.
                tileLayer.deleteAllTiles(function(success,err){

                    var zoom = getMinMaxZoom();
                    var extent = tileLayer.getExtentBuffer(0,map.extent);

                    // Begin downloading tiles
                    tileLayer.prepareForOffline(zoom.min, zoom.max, 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");
                            }
                            else
                            {
                                alert("Tile download complete");
                            }

                            btnGetTiles.innerHTML = '1. Download Tiles';
                        }
                        return _wantToCancel; //determines if a cancel request has been issued
                    });
                });
            }

            // Force the tileLayer between online and offline
            function goOnlineOffline(){
                if(btnOnlineOffline.innerHTML == "2. Go Offline"){
                    btnOnlineOffline.innerHTML = "2. Go Online";
                    tileLayer.goOffline();
                    document.body.style.backgroundColor = "red";
                    console.log("tileLayer is offline");
                }
                else{
                    btnOnlineOffline.innerHTML = "2. Go Offline";
                    tileLayer.goOnline();
                    document.body.style.backgroundColor = "black";
                    console.log("tileLayer is online");
                }
            }


            // Set the tileLayer online or offline.
            // When set to offline, the map will look for tiles in the tiles database
            function updateState(){
                if(Offline.state === 'up'){
                    if(typeof tileLayer != "undefined") tileLayer.goOnline();
                }
                else{
                    if(typeof tileLayer != "undefined") tileLayer.goOffline();
                }
            }

            // Utility function to validate min and max zoom settings of the map
            function getMinMaxZoom(){

                var zoom = {};
                var min = tileLayer.getLevel() + minZoomAdjust;
                var max = tileLayer.getLevel() + maxZoomAdjust;
                zoom.max = Math.min(mMaxZoom, max);  //prevent errors by setting the tile layer floor
                zoom.min = Math.max(mMinZoom, min);   //prevent errors by setting the tile layer ceiling

                return zoom;
            }

            function panLeft(){
                map.panLeft();
            }

        });
    </script>
</body>
</html>

                            
                        
NOTE: Replace paths with your references.