0

I am developing a Cordova application using the ArcGIS Javascript SDK. One minor annoyance I have run into that I can not quite figure out is why the BaseMapToggle & GeoLocate options require a double click on the iOS application. The web demo shows that this works on a single click. A minor issue, but not very initiative when most everything on mobile is a single touch event. Here is my code:

//NOTE: gMapVaults is a multi-dimension array declared  above
var map,toggle,geoLocate;
require([
    "esri/map",
    "esri/dijit/BasemapToggle",
    "esri/dijit/LocateButton",
    "esri/geometry/Point",
     "esri/symbols/SimpleMarkerSymbol", 
     "esri/symbols/Font",
     "esri/symbols/TextSymbol", 
     "esri/symbols/SimpleLineSymbol", 
     "esri/Color",
    "esri/graphic", 
    "esri/layers/GraphicsLayer",
    "dojo/domReady!"
], function(
  Map, BasemapToggle, LocateButton, Point, SimpleMarkerSymbol, Font, TextSymbol, SimpleLineSymbol, Color, Graphic, GraphicsLayer
)  {
      map = new Map("map", {
        center: [gMapVaults[0][2],gMapVaults[0][1]],
        zoom: 18,
        basemap: "satellite"
      });

        toggle = new BasemapToggle({
            map: map,
            visible: true,
            basemap: "streets"
          }, "BasemapToggle");

        geoLocate = new LocateButton({
            map: map
          }, "LocateButton");

        toggle.startup();
        geoLocate.startup();

        map.on("load", function() {
            for (var i=0;i<gMapVaults.length;i++){
                    var p = new Point(gMapVaults[i][2], gMapVaults[i][1]);
                    var s = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 20,
                        new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
                        new Color([255,0,0]), 1),
                        new Color([0,255,0,0.25]));
                    var g = new Graphic(p, s);
                    g.setAttributes({
                        name: gMapVaults[i][0]
                    });
                    map.graphics.add(g);

                    var t = new TextSymbol(gMapVaults[i][0]);
                    t.setOffset(0,12);
                    var p2 = new Point(gMapVaults[i][2], gMapVaults[i][1]);
                    var g2 = new Graphic(p2, t);
                    map.graphics.add(g2);
            }

        });

});
1

I could not replicate this behavior:

  • ArcGIS API for JavaScript: version 3.17
  • iOS: "5.0 (iPhone; CPU iPhone OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13F69 (5885985328)"
  • cordova: version 6.2.0

Make sure to add the geolocation plugin via cordova plugin add cordova-plugin-geolocation

The code has been modified from the default Hello Cordova boilerplate app, Basemap Toggle sample, and Locate Button sample.

index.html

    <!DOCTYPE html>
    <!--
        Licensed to the Apache Software Foundation (ASF) under one
        or more contributor license agreements.  See the NOTICE file
        distributed with this work for additional information
        regarding copyright ownership.  The ASF licenses this file
        to you under the Apache License, Version 2.0 (the
        "License"); you may not use this file except in compliance
        with the License.  You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

        Unless required by applicable law or agreed to in writing,
        software distributed under the License is distributed on an
        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
         KIND, either express or implied.  See the License for the
        specific language governing permissions and limitations
        under the License.
    -->
    <html>
        <head>
            <!--
            Customize this policy to fit your own app's needs. For more guidance, see:
                https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
            Some notes:
                * gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
                * https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
                * Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
                    * Enable inline JS: add 'unsafe-inline' to default-src
            <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
    -->


            <meta http-equiv="Content-Security-Policy"
                  content="
                  frame-src
                      'self'
                                        gap:
                      http://static.arcgis.com
                      https://static.arcgis.com
                      http://services.arcgisonline.com
                      https://services.arcgisonline.com
                      http://server.arcgisonline.com
                      http://js.arcgis.com
                      https://js.arcgis.com;
                  connect-src
                      'self'
                                        http:
                      http://static.arcgis.com
                      https://static.arcgis.com
                      https://services.arcgisonline.com;
                    default-src
                        'self'
                                        data:
                                        gap:
                        http:
                      http://static.arcgis.com
                      https://static.arcgis.com
                      http://services.arcgisonline.com
                      https://services.arcgisonline.com
                      https://server.arcgisonline.com
                      http://server.arcgisonline.com
                      http://js.arcgis.com
                      https://js.arcgis.com;
                    font-src
                        'self'
                        http:
                                        http://js.arcgis.com
                                        https://js.arcgis.com
                        data:;
                    style-src 
                      'self'
                      http:
                      http://js.arcgis.com
                      https://js.arcgis.com
                      'unsafe-inline';
                    script-src 
                      'self'
                      http:
                      http://js.arcgis.com
                      https://js.arcgis.com
                      'unsafe-inline'
                      'unsafe-eval'">

            <meta name="format-detection" content="telephone=no">
            <meta name="msapplication-tap-highlight" content="no">
            <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
            <link rel="stylesheet" type="text/css" href="css/index.css">
                    <link rel="stylesheet" href="https://js.arcgis.com/3.17/esri/css/esri.css">
            <title>Hello World</title>
        </head>
        <body>
            <div class="app">
                <h1>Apache Cordova</h1>
                <div id="deviceready" class="blink">
                    <p class="event listening">Connecting to Device</p>
                    <p class="event received">Device is Ready</p>
                </div>
            </div>
            <div id="map"></div>
                <div id="LocateButton"></div>
                <div id="BasemapToggle"></div>

            <script type="text/javascript" src="cordova.js"></script>
            <script src="https://js.arcgis.com/3.17"></script>
            <script type="text/javascript" src="js/index.js"></script>
        </body>
    </html>

index.css

    /*
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements.  See the NOTICE file
     * distributed with this work for additional information
     * regarding copyright ownership.  The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the
     * "License"); you may not use this file except in compliance
     * with the License.  You may obtain a copy of the License at
     *
     * http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing,
     * software distributed under the License is distributed on an
     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     * KIND, either express or implied.  See the License for the
     * specific language governing permissions and limitations
     * under the License.
     */
    * {
        -webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */
    }

    body {
        -webkit-touch-callout: none;                /* prevent callout to copy image, etc when tap to hold */
        -webkit-text-size-adjust: none;             /* prevent webkit from resizing text to fit */
        -webkit-user-select: none;                  /* prevent copy paste, to allow, change 'none' to 'text' */
        background-color:#E4E4E4;
        background-image:linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
        background-image:-webkit-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
        background-image:-ms-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
        background-image:-webkit-gradient(
            linear,
            left top,
            left bottom,
            color-stop(0, #A7A7A7),
            color-stop(0.51, #E4E4E4)
        );
        background-attachment:fixed;
        font-family:'HelveticaNeue-Light', 'HelveticaNeue', Helvetica, Arial, sans-serif;
        font-size:12px;
        height:100%;
        margin:0px;
        padding:0px;
        text-transform:uppercase;
        width:100%;
    }

    /* Portrait layout (default) */
    .app {
            display:none;
        background:url(../img/logo.png) no-repeat center top; /* 170px x 200px */
        position:absolute;             /* position in the center of the screen */
        left:50%;
        top:50%;
        height:50px;                   /* text area height */
        width:225px;                   /* text area width */
        text-align:center;
        padding:180px 0px 0px 0px;     /* image height is 200px (bottom 20px are overlapped with text) */
        margin:-115px 0px 0px -112px;  /* offset vertical: half of image height and text area height */
                                       /* offset horizontal: half of text area width */
    }

    /* Landscape layout (with min-width) */
    @media screen and (min-aspect-ratio: 1/1) and (min-width:400px) {
        .app {
            background-position:left center;
            padding:75px 0px 75px 170px;  /* padding-top + padding-bottom + text area = image height */
            margin:-90px 0px 0px -198px;  /* offset vertical: half of image height */
                                          /* offset horizontal: half of image width and text area width */
        }
    }

    h1 {
        font-size:24px;
        font-weight:normal;
        margin:0px;
        overflow:visible;
        padding:0px;
        text-align:center;
    }

    .event {
        border-radius:4px;
        -webkit-border-radius:4px;
        color:#FFFFFF;
        font-size:12px;
        margin:0px 30px;
        padding:2px 0px;
    }

    .event.listening {
        background-color:#333333;
        display:block;
    }

    .event.received {
        background-color:#4B946A;
        display:none;
    }

    @keyframes fade {
        from { opacity: 1.0; }
        50% { opacity: 0.4; }
        to { opacity: 1.0; }
    }

    @-webkit-keyframes fade {
        from { opacity: 1.0; }
        50% { opacity: 0.4; }
        to { opacity: 1.0; }
    }

    .blink {
        animation:fade 3000ms infinite;
        -webkit-animation:fade 3000ms infinite;
    }

    html, body, #map {
        width: 100%;
        height: 100%;
    }

    #LocateButton {
      position: absolute;
      top: 95px;
      left: 20px;
      z-index: 50;
    }

    #BasemapToggle {
      position: absolute;
      top: 25px;
      right: 20px;
      z-index: 50;
    }

index.js

    /*
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements.  See the NOTICE file
     * distributed with this work for additional information
     * regarding copyright ownership.  The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the
     * "License"); you may not use this file except in compliance
     * with the License.  You may obtain a copy of the License at
     *
     * http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing,
     * software distributed under the License is distributed on an
     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     * KIND, either express or implied.  See the License for the
     * specific language governing permissions and limitations
     * under the License.
     */
    var app = {
        // Application Constructor
        initialize: function() {
            this.bindEvents();
        },
        // Bind Event Listeners
        //
        // Bind any events that are required on startup. Common events are:
        // 'load', 'deviceready', 'offline', and 'online'.
        bindEvents: function() {
            document.addEventListener('deviceready', this.onDeviceReady, false);
        },
        // deviceready Event Handler
        //
        // The scope of 'this' is the event. In order to call the 'receivedEvent'
        // function, we must explicitly call 'app.receivedEvent(...);'
        onDeviceReady: function() {
            app.receivedEvent('deviceready');
        },
        // Update DOM on a Received Event
        receivedEvent: function(id) {
            var parentElement = document.getElementById(id);
            var listeningElement = parentElement.querySelector('.listening');
            var receivedElement = parentElement.querySelector('.received');

            listeningElement.setAttribute('style', 'display:none;');
            receivedElement.setAttribute('style', 'display:block;');

                require([
                  "esri/map", 
                         "esri/dijit/BasemapToggle",
                  "esri/dijit/LocateButton",
                  "dojo/domReady!"
                ], function(
                  Map, BasemapToggle, LocateButton
                )  {

                 var map = new Map("map", {
                    center: [-56.049, 38.485],
                    zoom: 3,
                    basemap: "streets"
                  });

                  var geoLocate = new LocateButton({
                    map: map
                  }, "LocateButton");
                  geoLocate.startup();


                        var toggle = new BasemapToggle({
                map: map,
                visible: true,
                basemap: "satellite"
              }, "BasemapToggle");
                        toggle.startup();
                });


            console.log('Received Event: ' + id);
        }
    };

    app.initialize();
  • I copied this as well and confirmed that it does work as designed here. The only thing that may be conflicting is that I am using the Framework7 CSS framework. The view that the map is contained within had a z-index of 5000, but removing that value or giving the basemaptoggle a higher value did not seem to resolve the issue. – Nate23VT Jul 13 '16 at 15:33
0

I also was unable to replicate with very similar configuration to @lheberlie.

The only other thing I can think of is to make sure there aren't any other HTML elements hovering above the Map's Z-level.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.