<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>US Movie Genres by County</title>
<link rel="stylesheet" href="//js.arcgis.com/3.14/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="//js.arcgis.com/3.14/esri/css/esri.css">
<link rel="stylesheet" href="./css/styles.css" />
</head>
<body class="claro">
<div id="esri-map-container"></div>
<div id="esri-basemapgallery-container" class="esriBasemapGallery"></div>
<div id="esri-colorinfoslider-container">
<div id="title"></div>
<hr>
<div>
Theme:
<select id="color-renderer-theme">
<option value="high-to-low" selected>High to low</option>
<option value="above-and-below">Above and below</option>
<option value="centered-on">Centered on</option>
<option value="extremes">Extremes</option>
</select>
</div>
<div id="esri-colorinfoslider"></div>
<input type="checkbox" id="sliderZoomButton"/> Show histogram detail
</div>
<pre id="results"></pre>
<script src="//js.arcgis.com/3.14/"></script>
</body>
</html>
require([
"dojo/_base/array",
"dojo/dom",
"dojo/number",
"dojo/on",
"esri/basemaps",
"esri/Color",
"esri/dijit/Basemap",
"esri/dijit/BasemapGallery",
"esri/dijit/ColorInfoSlider",
"esri/dijit/util/busyIndicator",
"esri/InfoTemplate",
"esri/layers/FeatureLayer",
"esri/map",
"esri/plugins/FeatureLayerStatistics",
"esri/renderers/smartMapping",
"esri/symbols/SimpleFillSymbol",
"esri/symbols/SimpleLineSymbol",
"dojo/domReady!"
], function (
array, dom, number, on,
esriBasemaps, Color, Basemap, BasemapGallery, ColorInfoSlider, busyIndicator,
InfoTemplate, FeatureLayer, Map, FeatureLayerStatistics, smartMapping,
SimpleFillSymbol, SimpleLineSymbol
){
var fipsLookup = {"30": "MT", "54": "WV", "37": "NC", "22": "LA", "45": "SC", "36": "NY", "49": "UT", "08": "CO", "24": "MD", "25": "MA", "26": "MI", "27": "MN", "06": "CA", "21": "KY", "04": "AZ", "23": "ME", "46": "SD", "47": "TN", "44": "RI", "09": "CT", "42": "PA", "29": "MO", "40": "OK", "41": "OR", "35": "NM", "05": "AR", "28": "MS", "02": "AK", "13": "GA", "01": "AL", "20": "KS", "11": "DC", "10": "DE", "39": "OH", "38": "ND", "15": "HI", "48": "TX", "17": "IL", "16": "ID", "55": "WI", "18": "IN", "31": "NE", "56": "WY", "51": "VA", "50": "VT", "53": "WA", "34": "NJ", "19": "IA", "32": "NV", "12": "FL", "33": "NH"};
// Only show the movie genre fields in the InfoTemplate
var movieFieldsArray = [ "MP20049a_B", "MP20050a_B", "MP20051a_B", "MP20052a_B", "MP20053a_B", "MP20054a_B", "MP20055a_B", "MP20056a_B", "MP20057a_B", "MP20058a_B"];
// --------------------------------------------------------------------
// variables that change with UI interaction
//
// BasemapGallery selection and ColorInfoSlider theme changes
// --------------------------------------------------------------------
var basemap = "gray";
var theme = "high-to-low";
var fieldName = "MP20044a_B"; // Attd a movie in /6 mos
var url = "http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/US_Movie_Genre_Stats/FeatureServer/0";
var mapOptions = {basemap: basemap, center: [-115.84, 36.14], level: 9};
var map = new Map("esri-map-container", mapOptions);
var busyIndicator = busyIndicator.create({target: "esri-colorinfoslider", imageUrl: "images/busy-indicator.gif", backgroundOpacity: 0});
// --------------------------------------------------------------------
// InfoTemplate and InfoWindow highlight symbol
// --------------------------------------------------------------------
FormatMovieGenreCount = function (value, key, data, options){
// console.log("value: ", value, " key: ", key, " data: ", data, " options: ", options);
return number.format(value);
};
FormatFIPSToStateAbbr = function (value, key, data, options){
// console.log("value: ", value, " key: ", key, " data: ", data, " options: ", options);
return fipsLookup[value];
};
// InfoWindow FillSymbol highlight
var sfs = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
new Color("#5c5c5c"), 4), new Color("#fafafa")
);
map.infoWindow.set("fillSymbol", sfs);
var geoenrichedFeatureLayer = new FeatureLayer(url, {outFields: ["*"]});
var featureLayerStatistics = new FeatureLayerStatistics({layer: geoenrichedFeatureLayer, visible: false});
// --------------------------------------------------------------------
// Create the ColorInfoSlider widget and initialize. Pass in an initial
// stops parameter, will be replaced later.
// --------------------------------------------------------------------
var colorInfoSlider = new ColorInfoSlider({
colorInfo: {
stops:[
{color: new Color([92,92,92]), label: "50", value: 50},
{color: new Color([92,92,92]), label: "51", value: 51}
]
}
}, "esri-colorinfoslider");
colorInfoSlider.startup();
// --------------------------------------------------------------------
// Create the BasemapGallery widget and populate it using the settings
// from esri/basemaps
// --------------------------------------------------------------------
var basemapGallery = new BasemapGallery({
showArcGISBasemaps: false,
map: map
}, "esri-basemapgallery-container");
for (var basemap_key in esriBasemaps) {
var esriBasemap = esriBasemaps[basemap_key];
basemapGallery.add(
new Basemap({
id: basemap_key,
layers: esriBasemap.baseMapLayers,
thumbnailUrl: esriBasemap.thumbnailUrl,
title: esriBasemap.title
})
);
if (basemap_key == basemap) {
basemapGallery.select(basemap_key);
}
}
basemapGallery.startup();
basemapGallery.on("selection-change", function (event){
basemap = event.target.getSelected().id;
//console.log("New basemap:", basemap);
if (geoenrichedFeatureLayer.loaded) {
updateSmartMapping();
}
});
// --------------------------------------------------------------------
// After the FeatureLayer loads, format the Popup and calculate the
// suggested scale range from the FeatureLayerStatistics plugin
// --------------------------------------------------------------------
geoenrichedFeatureLayer.on("load", function (){
//console.log("FeatureLayer loaded");
map.addLayer(geoenrichedFeatureLayer);
//Configure InfoTemplate on FeatureLayer
var content = "<table>";
content += "<tr><td colspan='2' class='movie-summary'>Popular: <b>${PredominantMovieGenre}</b> by ${PredominantMovieGenreByPercent}%</td></tr>";
content += "<tr><td colspan='2' class='movie-desc'>Movie attendance / 6 months by Genre</td></tr>";
array.forEach(geoenrichedFeatureLayer.fields, function (field){
// console.log("%s: %s", field.name, movieFieldsArray.indexOf(field.name));
if (movieFieldsArray.indexOf(field.name) !== -1) {
content += "<tr><td class='attr-name'><b>" + field.alias.replace("Movie genre seen at theater/6 mo: ",
"") + "</b></td><td class=\"attr-value\">${" + field.name + ":FormatMovieGenreCount()}</td></tr>";
}
});
content += "</table>";
geoenrichedFeatureLayer.setInfoTemplate(new InfoTemplate("${NAME} County, ${STATE_FIPS:FormatFIPSToStateAbbr()}", content));
//ColorInfoSlider panel title
dom.byId("title").innerHTML = geoenrichedFeatureLayer.name + "<br>" + array.filter(geoenrichedFeatureLayer.fields, function (field){
return field.name === fieldName;
})[0].alias;
//suggest scale range
featureLayerStatistics.getSuggestedScaleRange().then(function (scaleRange){
//console.log("suggested scale range", scaleRange);
geoenrichedFeatureLayer.setScaleRange(scaleRange.minScale, scaleRange.maxScale);
map.setScale(scaleRange.minScale);
});
updateSmartMapping();
});
// --------------------------------------------------------------------
// Function for calling smartMapping and FeatureLayerStatistics plugin
// --------------------------------------------------------------------
function updateSmartMapping(){
//console.log("updateSmartMapping");
busyIndicator.show();
//create and apply color renderer
smartMapping.createColorRenderer({
layer: geoenrichedFeatureLayer,
field: fieldName,
basemap: basemap,
theme: theme
}).then(function (colorRenderer){
//console.log("create color renderer is generated", colorRenderer);
var data = colorRenderer.renderer.toJson();
var js = JSON.stringify(data, null, 2);
document.getElementById('results').innerHTML = js;
if (!geoenrichedFeatureLayer.visible) {
geoenrichedFeatureLayer.show();
}
geoenrichedFeatureLayer.setRenderer(colorRenderer.renderer);
geoenrichedFeatureLayer.redraw();
// --------------------------------------------------------------------
// Calculate the Histogram
// --------------------------------------------------------------------
featureLayerStatistics.getHistogram({
field: fieldName,
numBins: 10
}).then(function (histogram){
//console.log("histogram is created", histogram);
// --------------------------------------------------------------------
// Update the ColorInfoSlider and apply FeatureLayerStatistics histogram
// --------------------------------------------------------------------
var sliderHandleInfo = getSliderHandlePositions(theme);
colorInfoSlider.set("colorInfo", colorRenderer.renderer.visualVariables[0]);
colorInfoSlider.set("minValue", colorRenderer.statistics.min);
colorInfoSlider.set("maxValue", colorRenderer.statistics.max);
colorInfoSlider.set("statistics", colorRenderer.statistics);
colorInfoSlider.set("histogram", histogram);
colorInfoSlider.set("handles", sliderHandleInfo["handles"]);
colorInfoSlider.set("primaryHandle", sliderHandleInfo["primaryHandle"]);
busyIndicator.hide();
// --------------------------------------------------------------------
// process slider handle changes
// Object with keys: type, field, normalizationField, stops
// --------------------------------------------------------------------
colorInfoSlider.on("handle-value-change", function (sliderValueChange){
//console.log("handle-value-change", sliderValueChange);
geoenrichedFeatureLayer.renderer.setVisualVariables([sliderValueChange]);
geoenrichedFeatureLayer.redraw();
var data = geoenrichedFeatureLayer.renderer.toJson();
var js = JSON.stringify(data, null, 2);
document.getElementById('results').innerHTML = js;
});
// recreate the renderer when the theme changes
dom.byId("color-renderer-theme").onchange = function (){
theme = this.value;
busyIndicator.show();
smartMapping.createColorRenderer({
layer: geoenrichedFeatureLayer,
field: fieldName,
basemap: basemap,
theme: theme
}).then(function (colorRenderer){
busyIndicator.hide();
var data = colorRenderer.renderer.toJson();
var js = JSON.stringify(data, null, 2);
document.getElementById('results').innerHTML = js;
//console.log("create color renderer is generated", colorRenderer);
geoenrichedFeatureLayer.setRenderer(colorRenderer.renderer);
geoenrichedFeatureLayer.redraw();
var sliderHandleInfo = getSliderHandlePositions(theme);
colorInfoSlider.set("minValue", colorRenderer.statistics.min);
colorInfoSlider.set("maxValue", colorRenderer.statistics.max);
colorInfoSlider.set("colorInfo", colorRenderer.renderer.visualVariables[0]);
colorInfoSlider.set("handles", sliderHandleInfo["handles"]);
colorInfoSlider.set("primaryHandle", sliderHandleInfo["primaryHandle"]);
}).otherwise(function (error){
busyIndicator.hide();
colorInfoSlider.showHistogram = false;
console.log("An error occurred while changing the theme, Error: %o", error);
});
};
// update the slider's zoomed state
dom.byId("sliderZoomButton").onchange = function(){
var zoomOptions,
bottomHandlerValue,
topHandlerValue,
zoomInViewBottomValue,
zoomInViewTopValue,
getHistogramParams;
// If checked
if(dom.byId("sliderZoomButton").checked){
// Get current handle values
bottomHandlerValue = colorInfoSlider.get("colorInfo").stops[0].value;
topHandlerValue = colorInfoSlider.get("colorInfo").stops[4].value;
// Calculate the minimum and maximum values of the zoomed slider
zoomInViewBottomValue = bottomHandlerValue - (topHandlerValue - bottomHandlerValue) / 3;
zoomInViewTopValue = topHandlerValue + (topHandlerValue - bottomHandlerValue) / 3;
// Fallback to statistics if values are out of expected range
if (zoomInViewBottomValue < colorRenderer.statistics.min) {
zoomInViewBottomValue = colorRenderer.statistics.min;
}
if (zoomInViewTopValue > colorRenderer.statistics.max) {
zoomInViewTopValue = colorRenderer.statistics.max;
}
// Histogram generation using new values
getHistogramParams = {
field: fieldName,
numBins: 10,
minValue: zoomInViewBottomValue,
maxValue: zoomInViewTopValue
};
// Use new FeatureLayer statisticsPlugin module
geoenrichedFeatureLayer.statisticsPlugin.getHistogram(getHistogramParams).then(function(histogram){
zoomOptions = {
"histogram": histogram,
minSliderValue: zoomInViewBottomValue,
maxSliderValue: zoomInViewTopValue
};
// Update the Slider
colorInfoSlider.set("zoomOptions", zoomOptions);
});
}else{
// Unzoom the Slider
colorInfoSlider.set("zoomOptions", null);
}
};
}).otherwise(function (error){
busyIndicator.hide();
console.log("An error occurred while calculating the histogram, Error: %o", error);
});
}).otherwise(function (error){
busyIndicator.hide();
console.log("An error occurred while creating the color renderer, Error: %o", error);
});
}
// --------------------------------------------------------------------
// Update ColorInfoSlider handle positions based upon theme chosen.
// --------------------------------------------------------------------
function getSliderHandlePositions(theme){
switch (theme) {
case "high-to-low":
return {
handles: [0, 4],
primaryHandle: null
};
case "above-and-below":
return {
handles: [0, 2, 4],
primaryHandle: 2
};
case "centered-on":
return {
handles: [0, 2, 4],
primaryHandle: 2
};
case "extremes":
return {
handles: [0, 2, 4],
primaryHandle: null
};
case "group-similar":
return {
handles: [0, 1, 2, 3, 4],
primaryHandle: null
};
}
}
});
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |