Customize Story Map Shortlist to add photo in header

4653
26
Jump to solution
10-06-2017 03:25 PM
NBurling
New Contributor II

I am working with the Storymaps shortlist app and have seen some beautiful examples in the gallery but I can't figure out how reproduce some of the features. For example this map as a photo as the header. Can someone help me figure out how I can do that? thanks

0 Kudos
26 Replies
BrandonPrice
Occasional Contributor

Hi Nathan,

I am using a dojo button to call from with the id "toggle basemap" in the html for my script:

var togglebasemap = dom.byId("togglebasemap");

   on(togglebasemap, "click", function () {

   var baseLyr = app.map.getLayer(app.map.layerIds[0]);

        if(baseLyr.url === "https://www.arcgis.com/sharing/rest/content/items/0e0aa048cb9a42de91ae287fc5632fac/resources/styles/..."){

      app.map.removeLayer(baseLyr);

   var tiled = new ArcGISTiledMapServiceLayer("http://public.gis.lacounty.gov/public/rest/services/LACounty_Cache/LACounty_Base/MapServer");

      app.map.addLayer(tiled, 0);

    } else if(baseLyr.url === "http://public.gis.lacounty.gov/public/rest/services/LACounty_Cache/LACounty_Base/MapServer"){

     app.map.removeLayer(baseLyr);

   var vectorTileLayer = new   VectorTileLayer("http://www.arcgis.com/sharing/rest/content/items/0e0aa048cb9a42de91ae287fc5632fac/resources/styles/r...");

   app.map.addLayer(vectorTileLayer, 0);

  }

});

The bottom part seems off maybe.

Brandon

0 Kudos
BrandonPrice
Occasional Contributor

The toggle only seems to fire within each map instance. The button is basically removing off the [0] layer set in each web map and then creating a new tiled layer which is added to the map. 

0 Kudos
BrandonPrice
Occasional Contributor

var vectorTileLayer = new VectorTileLayer({
styleUrl: "https://www.arcgis.com/sharing/rest/content/items/0e0aa048cb9a42de91ae287fc5632fac/resources/styles/...",
type: "VectorTileLayer"
});
var vectorBasemap = new Basemap({
layers: [vectorTileLayer],
title: "Vector",
thumbnailUrl: "https://caltrans.maps.arcgis.com/sharing/rest/content/items/0e0aa048cb9a42de91ae287fc5632fac/info/th....."
});
var imageryLayer = new BasemapLayer({
url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"
});
var imageryBasemap = new Basemap({
layers: [imageryLayer],
title: "Satellite",
thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/413fd05bbd7342f5991d5ec96f4f8b18/info/thumbnail/ima..."
});
var basemapGallery = new BasemapGallery({
map: app.map,
basemaps: [imageryBasemap],
showArcGISBasemaps: false
}, "basemapGallery");
basemapGallery.on("selection-change", function () {
if (basemapGallery.basemaps[0] === vectorBasemap) {
basemapGallery.remove(vectorBasemap.id);
basemapGallery.add(imageryBasemap);
} else if (basemapGallery.basemaps[0] === imageryBasemap) {
basemapGallery.remove(imageryBasemap.id);
basemapGallery.add(vectorBasemap);
};
});
basemapGallery.startup();

This is what I have for the script (AMD not include). Does this look right? Is the css and html tricky? 

Brandon

0 Kudos
NathanHeick
Occasional Contributor II

Good Morning Brandon,

Let me provide all the code changes that I made for you.  It's similar to what you were doing, but I modified the style and made the widget smaller as the window shrinks.

1.  index.html - Here I made the following CSS changes.

#basemapGallery {

    position: absolute;

    bottom: 55px;

    right: 10px;

    z-index: 50;

}

.esriBasemapGalleryNode {

    border: 1px solid #ccc;

    box-shadow: 0px 0px 7px #000;

    -moz-box-shadow: 0px 0px 7px #000;

    -webkit-box-shadow: 0px 0px 7px #000;

}

.esriBasemapGalleryLabelContainer {

   font-size: 12px;

   background-color: #FFFFFF;

   height: 1.75em;

   border-top: 1px solid #ccc;

}

.esriBasemapGalleryThumbnail {

  border: 0px;

  margin: 0px;

  width: 100%;

  box-shadow: none;

  -moz-box-shadow: none;

  -webkit-box-shadow: none;

}

.esriBasemapGallerySelectedNode .esriBasemapGalleryThumbnail {

    border: 0px;

    margin: 0px;

}

Then, I added a div called basemapGallery inside the map div.

<div id="map">

    <div id="basemapGallery"></div>

</div>

2.  Core.js - Here I added the following code inside the function initializeUI to create and configure the basemap gallery.

 var topoLayer = new BasemapLayer({

    url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer"

});

var topoBasemap = new Basemap({

       layers: [topoLayer],

    title: "Topo",

    thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/6e03e8c26aad4b9c92a87c1063ddb0e3/info/thumbnail/top..."

});

var imageryLayer = new BasemapLayer({

    url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"

});

var hybridReferenceLayer = new BasemapLayer({

    styleUrl: "http://yourstyleurl",

    type: "VectorTileLayer"

});

var imageryBasemap = new Basemap({

         layers: [imageryLayer, hybridReferenceLayer],

     title: "Satellite",

     thumbnailUrl: "http://www.arcgis.com/sharing/rest/content/items/413fd05bbd7342f5991d5ec96f4f8b18/info/thumbnail/ima..."

});

var basemapGallery = new BasemapGallery({

       map: app.map,

       basemaps: [imageryBasemap],

    showArcGISBasemaps: false

}, "basemapGallery");

basemapGallery.on("selection-change", function () {

    if (basemapGallery.basemaps[0] === topoBasemap) {

             basemapGallery.remove(topoBasemap.id);

             basemapGallery.add(imageryBasemap);

    } else if (basemapGallery.basemaps[0] === imageryBasemap) {

             basemapGallery.remove(imageryBasemap.id);

             basemapGallery.add(topoBasemap);

        };

       _mainView.resizeBasemapGallery();

});

basemapGallery.startup();

3.  MainView.js - Here I added the following code inside the constructor function for the MainView class.  This resizes the basemap gallery widget based on how big the screen is.

this.resizeBasemapGallery = function() {

    if ($('.map .logo-sm').length === 1) {

        $('.esriBasemapGalleryLabelContainer').css('display', 'none');

        $('#basemapGallery').css({

            'height': '40px',

            'width': '72px',

            'bottom': '30px',

            'right': '0px'

              });

        $('.esriBasemapGalleryNode').css({

            'height': '35px',

            'width': '52px'

              });

        $('.esriBasemapGalleryThumbnail').css({

            'height': '33px',

            'width': '50px'

              });

       }

    else {

        $('.esriBasemapGalleryLabelContainer').css('display', 'block');

        $('#basemapGallery').css({

            'height': '95px',

            'width': '120px',

            'bottom': '55px',

            'right': '10px'

              });

        $('.esriBasemapGalleryNode').css({

            'height': '88px',

            'width': '98px'

              });

        $('.esriBasemapGalleryThumbnail').css({

            'height': '67px',

            'width': '96px'

              });

       }

}

0 Kudos
BrandonPrice
Occasional Contributor

Hi Nathan,

Thanks for the sample. This is great material to work with. I am going mull over this for a bit and get back to this thread with the my final code. I don't have a div id=map. I am using a regular tabbed story map series downloaded from ArcGIS Online. Are you maybe using a hybrid story of some sort? Was yours downloaded off github or Agol?

-Brandon

0 Kudos
NathanHeick
Occasional Contributor II

No, I'm using a Shortlist story map, which also has tabs but only has one map.  I believe the one you are using has one map per tab.  When you switch tabs, it turns the map on the new tab on and the map on the previous tab off.

If you want to continue with the approach above, you would need to create one BasemapGallery widget for each map.  You would probably want to add a variable to _mainView that points to an array of the BasemapGallery widgets and they would be indexed the same way as the tabs and maps.  Then, you would add one more block of code to the on selection change callback function.  If the active map index equals the index of the BasemapGallery widget that was just selected, then call the select method on the BasemapGallery widgets of the other maps.  This will trigger the selection-change event on the non-active widgets, but they will just update themselves and not start an infinite loop.

It looks like the maps array is called app.maps.  The expression $('.mainMediaContainer.active').index() produces the index of the active tab.  You need to wrap the code in step 2 in a for loop iterating over app.maps.  Then, you need to add the condition I talked about above in the selection-change event handler to make the active widget update the non-active widgets.  You'll need to add divs inside each map div using jQuery to store the widgets.  Explore the DOM using the Developer Tools (F12) in most browsers to see the structure of the DOM.  You can also see how Esri uses jQuery and CSS classes to store some of the application state.

As for resizeBasemapGallery, I would probably add a parameter called index and modify the code to only apply to the tab with the given index.  Then, on a basemap selection-change, only resize the BasemapGallery widget for the active map.  I forgot something else.  I am calling resizeBasemapGallery in a few other places in the code so that it resizes when you change the window size, etc.  I can't look up those other places sometime.  The jQuery Pocket Reference from O'Reilly is a good way to pickup the basics of jQuery.  I started with the code from GitHub and set up Node and Grunt to automate the build process.

Have a good weekend!

Nathan

0 Kudos
BrandonPrice
Occasional Contributor

Wow Nathan. This is great. Thanks for your time explaining this. I checked out the shortlist to use for my project instead but it doesn't seem you can use anything other than point markers and not map services which are what my maps have. I am going to review what you found on  $('.mainMediaContainer.active').index() for the tabs. This is what I have so far (same solution as above that doesn't change all tabs, just active map, but with thumbnails instead of a button (like yours)):

var togglebasemap = dom.byId("togglebasemap");
on(togglebasemap, "click", function () {
var baseLyr = app.map.getLayer(app.map.layerIds[0]);
if(baseLyr.url === "https://www.arcgis.com/sharing/rest/content/items/0e0aa048cb9a42de91ae287fc5632fac/resources/styles/..."){
app.map.removeLayer(baseLyr);
var tiled = new ArcGISTiledMapServiceLayer("http://public.gis.lacounty.gov/public/rest/services/LACounty_Cache/LACounty_Base/MapServer");
app.map.addLayer(tiled, 0);
$('#togglebasemap').css('background-image', 'url(http://caltrans.maps.arcgis.com/sharing/rest/content/items/0e0aa048cb9a42de91ae287fc5632fac/info/thu...
} else if(baseLyr.url === "http://public.gis.lacounty.gov/public/rest/services/LACounty_Cache/LACounty_Base/MapServer"){
app.map.removeLayer(baseLyr);
var vectorTileLayer = new VectorTileLayer("http://www.arcgis.com/sharing/rest/content/items/0e0aa048cb9a42de91ae287fc5632fac/resources/styles/r...");
app.map.addLayer(vectorTileLayer, 0);
$('#togglebasemap').css('background-image', 'url(http://caltrans.maps.arcgis.com/sharing/rest/content/items/10df2279f9684e4a9f6a7f08febac2a9/info/thu...
}
});

I will repost with any changes.

Brandon

0 Kudos