Hide Table of Contents
Latest Samples
Image Layers
Mobile ArcGIS.com

Description

This sample uses jQueryMobile to build an application for mobile devices that displays ArcGIS.com web maps. jQueryMobile is a framework that simplifies the process of building an application that will work well on smart-phones like Android, iPhone and Blackberry Torch.

You can modify the application to use another webmap by appending a valid web map id to the sample url.

?webmap=1966ef409a344d089b001df85332608f

At version 2.4 a new mobile popup was added that is designed to work well when used with smaller map sizes. The mobile popup displays the title when the feature is clicked along with an arrow that lets users navigate to a new panel to view the item details.

This sample specifies a manifest file, this is a file with a list of resources that will be cached locally. Click here to view the manifest file used by this application. For more details about working with manifest files see the W3C working draft.

<html manifest="mobile.manifest">

Code

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!-- Sets whether a web application runs in full-screen mode. -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>Mobile Web Map</title>

<link rel="stylesheet" href="css/CustomTheme.css" />
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.css" />
<link rel="stylesheet" href="http://js.arcgis.com/3.9/js/esri/dijit/css/Gallery.css" />
<link rel="stylesheet" href="http://js.arcgis.com/3.9/js/esri/css/esri.css" />
<link rel="stylesheet" href="css/layout.css" />

<script src="http://code.jquery.com/jquery-1.9.0.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.js"></script>
<script src="//js.arcgis.com/3.9compact/"></script>

<script>
require([
  "dojo/_base/array",
  "dojo/_base/connect",
  "esri/Color",
  "dojo/dom",
  "dojo/dom-style",
  "dojo/keys",
  "esri/geometry/Extent",
  "esri/geometry/Point",
  "esri/graphic",
  "esri/SpatialReference",
  "dojo/on",
  "dojo/parser",
  "dojo/ready",
  "esri/arcgis/utils",
  "esri/dijit/BasemapGallery",
  "esri/dijit/Gallery",
  "esri/dijit/Legend",
  "esri/dijit/PopupMobile",
  "esri/InfoTemplate",
  "esri/layers/FeatureLayer",
  "esri/map",
  "esri/symbols/PictureMarkerSymbol",
  "esri/symbols/SimpleLineSymbol",
  "esri/symbols/SimpleMarkerSymbol",
  "esri/tasks/locator"],
    function (array, connect, Color, dom, domStyle, keys, Extent, Point, Graphic, SpatialReference, on, parser, ready, arcgisUtils, BasemapGallery, Gallery, Legend, PopupMobile, InfoTemplate, FeatureLayer, Map, PictureMarkerSymbol, SimpleLineSymbol, SimpleMarkerSymbol, Locator) {
      parser.parse();

      var map,
          locator,
          currentItem,
          arcgisURL = "http://arcgis.com/sharing/content/items/",
          bingMapsKey,
          urlObject,
          popup;

      ready(function () {
        $(document).ready(jQueryReady);
      });

      function jQueryReady() {
        //resize the map content section
        $('#mapcontent').height($(window).height());

        //onorientationchange doesn't always fire in a timely manner in Android so check for both orientationchange and resize
        var supportsOrientationChange = "onorientationchange" in window, orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";

        window.addEventListener(orientationEvent, function () {
          orientationChanged();
        }, false);

        urlObject = esri.urlToObject(document.location.href);
        urlObject.query = urlObject.query || {};

        // web map id
        var webmap = urlObject.query.webmap || "1e79439598494713b553f990a4040886";

        bingMapsKey = urlObject.query.bingMapsKey || "Akt3ZoeZ089qyG3zWQZSWpwV3r864AHStal7Aon21-Fyxwq_KdydAH32LTwhieA8";

        //initialize the geocoder
        locator = new Locator("http://tasks.arcgis.com/ArcGIS/rest/services/WorldLocator/GeocodeServer");
        on(locator, "onAddressToLocationsComplete", showResults);

        on(dom.byId("geolocate"), "click", getLocation);

        //create the map using the webmap id
        //create a mobile popup
        popup = new PopupMobile(null, dojo.create("div"));
        var mapDeferred = arcgisUtils.createMap(webmap, "map", {
          mapOptions  :{
            infoWindow:popup,
            autoResize: false
          },
          ignorePopups:false,
          bingMapsKey :bingMapsKey
        });
        mapDeferred.addCallback(function (response) {
          map = response.map;

          currentItem = response.itemInfo;
          $("#webmapTitle").html(currentItem.item.title);

          resizeMap();
        });

        $('#mapPage').bind('pageshow', function (event, ui) {
          orientationChanged();
        });

        $('#infoDialog').bind('pagebeforeshow', function (event, ui) {
          $("#webmapTitleInfo").html(currentItem.item.title);
          $("#snippet").html(currentItem.item.snippet);
          $("#description").html(currentItem.item.description);
          $("#mapThumbnail").attr("src", arcgisURL + currentItem.item.id + "/info/" + currentItem.item.thumbnail);
        });

        //add the legend
        $('#legendDialog').bind('pagebeforeshow', function (event, ui) {
          $(this).unbind(event);
          var layerInfo = [];
          array.forEach(currentItem.itemData.operationalLayers, function (layer) {
            if ((!layer.featureCollection) && (layer.layerObject)) {
              layerInfo.push({
                layer:layer.layerObject,
                title:layer.title
              });
            }
          });
          if (layerInfo.length > 0) {
            var legendDijit = new Legend({
              map       :map,
              layerInfos:layerInfo
            }, "legendDiv");
            legendDijit.startup();
          } else {
            $("#legendDiv").html("No operational layers");
          }
        });

        //setup the basemap gallery
        $('#detailDialog').bind('pagebeforeshow', function (event, ui) {
          $(this).unbind(event);
          $('#currentBasemap').html(currentItem.itemData.baseMap.title);
          var basemaps = new BasemapGallery({
            showArcGISBasemaps:true,
            map               :map
          });

          connect.connect(basemaps, "onLoad", function () {
            items = $.map(basemaps.basemaps, function (basemap) {
              return {
                thumbnailUrl:basemap.thumbnailUrl,
                id          :basemap.id,
                title       :basemap.title
              };
            });

            //display basemaps in the gallery
            var params = {};
            params.items = items;
            params.thumbnailStyle = "small";
            var gallery = new Gallery(params, "galleryDiv");

            connect.connect(gallery, "onSelect", function (item) {
              basemaps.select(item.id);
              //close the dialog
              $('#detailDialog').dialog('close');
            });

            gallery.startup();
          });
        });

        $('#searchDialog').bind('pagebeforeshow', function (event, ui) {
          $(this).unbind(event);
          connect.connect(dom.byId('search'), 'keypress', function(evt) {
            if(evt.keyCode === 13)
              findLocation();
          });
        });
      }

      //mark current location on map
      function zoomToLocation(location) {
        //clear existing graphics
        map.graphics.clear();
        $.mobile.hidePageLoadingMsg();
        var pt = esri.geometry.geographicToWebMercator(new Point(location.coords.longitude, location.coords.latitude));
        map.centerAndZoom(pt, 13);
        var symbol = new PictureMarkerSymbol("images/bluedot.png", 40, 40);
        map.graphics.add(new Graphic(pt, symbol));
      }

      function locationError(error) {
        switch (error.code) {
          case error.PERMISSION_DENIED:
            console.log("Location not provided");
            break;
          case error.POSITION_UNAVAILABLE:
            console.log("Current location not available");
            break;
          case error.TIMEOUT:
            console.log("Timeout");
            break;
          default:
            console.log("unknown error");
            break;
        }
      }

      function getLocation() {
        if (navigator.geolocation) {
          $.mobile.showPageLoadingMsg();
          //true hides the dialog
          //if you want to track as the user moves setup navigator.geolocation.watchPostion
          navigator.geolocation.getCurrentPosition(zoomToLocation, locationError);
        }
      }

      function findLocation() {
        var searchText = $("#search")[0].value;
        //clear existing list results
        $('#searchList li').remove();
        map.graphics.clear();
        var address = {
          'SingleLine':searchText
        };
        locator.addressToLocations(address, ["*"]);
      }

      function showResults(results) {
        //create a pick list of results
        $.each(results, function (i, result) {

          var li = $('<li class="linklist"/>');
          $('.linklist').click(function () {
            addResult(result);
          });

          //create the list content
          var content = "<a href='#'>" + result.address + "</a>";

          li.append(content);
          //add the list item to the feature type list
          $('#searchList').append(li);
        });
        //refresh the featurelist so the jquery mobile style is applied
        $('#searchList').listview('refresh');
      }

      function addResult(result) {
        //clear any existing graphics
        map.graphics.clear();
        //add selected geocode result to map and zoom
        var infoTemplate = new InfoTemplate("Result", "${*}");
        var r = Math.floor(Math.random() * 250);
        var g = Math.floor(Math.random() * 100);
        var b = Math.floor(Math.random() * 100);

        var symbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 10, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([r, g, b, 0.5]), 5), new Color([r, g, b, 0.9]));
        var wmloc = esri.geometry.geographicToWebMercator(result.location);
        var attr = {
          "Address":result.address
        };

        var graphic = new Graphic(wmloc, symbol, attr, infoTemplate);

        map.graphics.add(graphic);
        //convert point to extent and expand a bit
        var ptAttr = result.attributes;
        var esriExtent = new Extent(ptAttr.West_Lon, ptAttr.South_Lat, ptAttr.East_Lon, ptAttr.North_Lat, new SpatialReference({
          wkid:4326
        }));
        var extent = esri.geometry.geographicToWebMercator(esriExtent);
        map.setExtent(extent);
        //close the dialog
        $('#searchDialog').dialog('close');
      }

      function orientationChanged() {
        resizeMap();
      }

      function resizeMap() {
        if (map) {
          //resize map section
          $('#map').css("height", screen.height);
          $('#map').css("width", "auto");

          map.reposition();
          map.resize();
        }
      }
    }
)

</script>
</head>

<body>
  <div data-role="page" id="mapPage" class="page-map">
    <div data-role="header" data-theme='a'>
      <h1 id="webmapTitle">ArcGIS.com Map</h1>
      <a href="#infoDialog" id="info" data-rel="dialog" data-theme='b' class="ui-btn-right" data-icon="info" data-iconpos="notext"></a>
    </div>
    <div data-role="content" id="mapcontent">
      <div id="map"></div>
    </div>

    <!--Navbar-->
    <div id="footer" data-role="footer" data-theme='b'>
      <div data-role="navbar" class="customIcons">
        <ul>
          <li>
            <a id="geolocate" data-icon="custom" href="#">Locate</a>
          </li>
          <li>
            <a id="legend" data-icon="custom" href="#legendDialog" data-rel="dialog">Legend</a>
          </li>
          <li>
            <a id="details" data-icon="custom" href="#detailDialog" data-rel="dialog">Basemap</a>
          </li>
        </ul>
      </div>
    </div>
  </div>

  <!--Legend Dialog-->
  <div id="legendDialog" data-role="popup" data-theme="a">
    <div data-role="header">
      <h1><span>Legend</span></h1>
    </div>
    <div data-role="content">
      <div id="legendDiv"></div>
    </div>
  </div>

  <!--Details Dialog-->
  <div id="detailDialog" data-role="dialog">
    <div data-role="header">
      <h1><span>Map Content</span></h1>
    </div>
    <div data-role="content">
      <div>
        <b>Current Basemap:</b><span id="currentBasemap"></span>
      </div>
      <div id="galleryDiv"></div>
    </div>
  </div>

  <!--Map Details Dialog-->
  <div id="infoDialog" data-role="dialog">
    <div data-role="header" data-theme='b'>
      <h1><span id="webmapTitleInfo"></span></h1>
    </div>
    <div data-role="content">
      <div id="contentDiv">
        <div id="mapDetails">
          <img id="mapThumbnail" style="float:left;padding-right:5px;" width="100px;height:67px;" />
          <div id="snippet"></div>
          <div id="description"></div>
        </div>
      </div>
    </div>
  </div>
</body>
</html>