Commit 85084fcf authored by Peter Knoop's avatar Peter Knoop
Browse files

Merge branch 'knoop-bivariate'

parents 2adb1e7b dd3788b7
...@@ -40,8 +40,6 @@ body { ...@@ -40,8 +40,6 @@ body {
#username { #username {
font-weight: bold; font-weight: bold;
} }
#mainViewDiv { #mainViewDiv {
position: relative; position: relative;
z-index: 1; z-index: 1;
...@@ -67,12 +65,14 @@ body { ...@@ -67,12 +65,14 @@ body {
background-color: rgba(255,255,255,0.8) background-color: rgba(255,255,255,0.8)
} }
#legend { #parameter-picker {
padding: 0; position: absolute;
margin: 0; padding: 10px;
height: 300px; left: 100%;
width: 300px; transform: translate(-100%, 0);
background-color: rgba(255,255,255,0.8) background-color: white;
opacity: 0.6;
z-index: 3;
} }
#infoDiv { #infoDiv {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" /> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
<title>SharedAir</title> <title>SharedAir</title>
<link rel="shortcut icon" href="favicon.ico">
<link rel="stylesheet" href="sharedAir.css"> <link rel="stylesheet" href="sharedAir.css">
<link rel="stylesheet" href="https://js.arcgis.com/4.15/esri/themes/light/main.css" /> <link rel="stylesheet" href="https://js.arcgis.com/4.15/esri/themes/light/main.css" />
...@@ -13,14 +14,21 @@ ...@@ -13,14 +14,21 @@
</head> </head>
<body> <body>
<div id="anonymous-view"> <div id="anonymous-view" class="esri-widget">
<span id="sign-in" class="action">Sign In</span> <span id="sign-in" class="action">Sign In</span>
</div> </div>
<div id="authenticated-view"> <div id="authenticated-view" class="esri-widget">
<div id="title-view"> <div id="title-view">
<span id="username"></span>&nbsp;&nbsp;-&nbsp; <span id="username"></span>&nbsp;&nbsp;-&nbsp;
<span id="sign-out" class="action">Sign Out</span> <span id="sign-out" class="action">Sign Out</span>
</div> </div>
<div id="parameter-picker">
<label for="parameter-1">NWS Parameter:</label>
<select id="parameter-1-select"></select>
<br>
<label for="parameter-2-">Yale Parameter:</label>
<select id="parameter-2-select"></select>
</div>
<div id="mainViewDiv"></div> <div id="mainViewDiv"></div>
<div id="akViewDiv" class="esri-widget"></div> <div id="akViewDiv" class="esri-widget"></div>
<div id="hiViewDiv" class="esri-widget"></div> <div id="hiViewDiv" class="esri-widget"></div>
...@@ -32,6 +40,5 @@ ...@@ -32,6 +40,5 @@
<div id="sliderDiv" class"slider"></div> <div id="sliderDiv" class"slider"></div>
</div> </div>
</div> </div>
</div>
</body> </body>
</html> </html>
require([ require([
"esri/portal/Portal", 'esri/portal/Portal',
"esri/identity/OAuthInfo", 'esri/identity/OAuthInfo',
"esri/identity/IdentityManager", 'esri/identity/IdentityManager',
"esri/Map", 'esri/Map',
"esri/views/MapView", 'esri/views/MapView',
"esri/layers/FeatureLayer", 'esri/layers/FeatureLayer',
"esri/widgets/Slider", 'esri/widgets/Slider',
"dojo/dom-style", 'esri/widgets/Legend',
"dojo/dom-attr", 'esri/widgets/Home',
"dojo/on", 'esri/renderers/smartMapping/creators/relationship',
"dojo/dom" 'dojo/dom-style',
'dojo/dom-attr',
'dojo/on',
'dojo/dom'
], function( ], function(
Portal, Portal,
OAuthInfo, OAuthInfo,
...@@ -18,13 +21,16 @@ require([ ...@@ -18,13 +21,16 @@ require([
MapView, MapView,
FeatureLayer, FeatureLayer,
Slider, Slider,
Legend,
Home,
relationshipRendererCreator,
domStyle, domStyle,
domAttr, domAttr,
on, on,
dom dom
) { ) {
// Set Portal URL. // Set Portal URL.
const portalUrl = "https://umich.maps.arcgis.com/sharing" const portalUrl = 'https://umich.maps.arcgis.com/sharing'
// Set App ID for the ArcGIS Online item associated with this app. // Set App ID for the ArcGIS Online item associated with this app.
// If hosting the app locally, update the App Registration with the URI to its location, if needed. // If hosting the app locally, update the App Registration with the URI to its location, if needed.
// https://umich.maps.arcgis.com/home/item.html?id=b0f8c825ce4746e6ac89da2133905018 // https://umich.maps.arcgis.com/home/item.html?id=b0f8c825ce4746e6ac89da2133905018
...@@ -37,13 +43,13 @@ require([ ...@@ -37,13 +43,13 @@ require([
// Process login action. // Process login action.
// Listen for clicks on the sign-in link // Listen for clicks on the sign-in link
on(dom.byId("sign-in"), "click", function() { on(dom.byId('sign-in'), 'click', function() {
identityManager.getCredential(portalUrl); identityManager.getCredential(portalUrl);
}); });
// Process logout action. // Process logout action.
// Listen for clicks on the sign-out link // Listen for clicks on the sign-out link
on(dom.byId("sign-out"), "click", function() { on(dom.byId('sign-out'), 'click', function() {
identityManager.destroyCredentials(); identityManager.destroyCredentials();
// Reset page to initial state. // Reset page to initial state.
window.location.reload(); window.location.reload();
...@@ -64,71 +70,21 @@ require([ ...@@ -64,71 +70,21 @@ require([
// Once the portal has loaded successfully, then the user is signed in. // Once the portal has loaded successfully, then the user is signed in.
portal.load().then(function() { portal.load().then(function() {
console.log("start") console.log('start')
// Display username of logged in user. // Display username of logged in user.
dom.byId("username").innerHTML = portal.user.username; dom.byId('username').innerHTML = portal.user.username;
// Popup template for Yale state level data.
const popupTemplate = {
title:"{GeoType}: {NAME}",
content: [
{
type:"fields",
fieldInfos: [
{
fieldName: "TotalPop",
label: "Total Population"
},
{
fieldName: "happening",
label: "Believe global warming is happening"
},
{
fieldName: "happeningOppose",
label: "Do not believe global warming is happeing"
}
]
}
]
}
// Create a layer from the Yale State Level data
var layer = new FeatureLayer({
url: "https://services1.arcgis.com/4ezfu5dIwH83BUNL/arcgis/rest/services/Yale_State_Level/FeatureServer/0",
popupTemplate: popupTemplate,
outFields: ["NAME", "TotalPop", "happening", "happeningOppose"],
title: "U.S. States"
});
var basemapLayer = new FeatureLayer({
url: "https://services1.arcgis.com/4ezfu5dIwH83BUNL/arcgis/rest/services/USA_States_Generalized_share_air/FeatureServer/0",
title: "U.S. States"
});
var districtsLayer = new FeatureLayer({
url: "https://services1.arcgis.com/4ezfu5dIwH83BUNL/arcgis/rest/services/usa_116th_congressional_districts/FeatureServer/0",
popupTemplate: popupTemplate,
outFields: ["DISTRICTID", "NAME", "PARTY"],
title: "U.S. 116th Congressional Districts"
});
var map = new Map({
layers: [districtsLayer, basemapLayer, layer]
});
// Create the map views and assign to their respective containers/divs // Create the map views and assign to their respective containers/divs
const mainView = new MapView({ const mainView = new MapView({
container: "mainViewDiv", container: 'mainViewDiv',
map: map, //map: map,
popup: { popup: {
highlightEnabled: false, highlightEnabled: false,
dockEnabled: true, dockEnabled: true,
dockOptions: { dockOptions: {
breakpoint: false, breakpoint: false,
position: "bottom-right" position: 'bottom-center'
} }
}, },
extent: { extent: {
...@@ -145,13 +101,45 @@ require([ ...@@ -145,13 +101,45 @@ require([
wkid: 5070 wkid: 5070
}, },
ui: { ui: {
components: ["attribution"] components: ['attribution']
} }
}); });
// Create a layer from Perry's alert and Yale's opinion data at the level of Congressional Districts (115th).
const layer = new FeatureLayer({
//url: 'https://services1.arcgis.com/4ezfu5dIwH83BUNL/arcgis/rest/services/Yale_Congressional_District_115_Level/FeatureServer/0',
url: 'https://services1.arcgis.com/4ezfu5dIwH83BUNL/arcgis/rest/services/Yale_Perry_115_Congressional_Districts/FeatureServer/0',
//popupTemplate: popupTemplate,
//outFields: ['NAME', 'TotalPop', 'happening', 'happeningOppose'],
outFields: ['*'],
title: 'U.S. 115th Congressional Districts'
});
// Define initial set of parameters to display.
var parameter1 = 'FL';
var parameter2 = 'happening';
// Populate selection lists for parameters.
setParameterSelectionLists();
// Set relationship (or bivariate) renderer for data.
setRelationshipRenderer();
// Popup template for data.
var popupTemplate = '';
setPopupTemplate();
layer.popupTemplate = popupTemplate;
const map = new Map({
layers: [layer]
});
// Add map to mainView.
//mainView.map = map;
const akView = new MapView({ const akView = new MapView({
container: "akViewDiv", container: 'akViewDiv',
map: map, map: map,
extent: { extent: {
xmin: 396381, xmin: 396381,
...@@ -171,10 +159,10 @@ require([ ...@@ -171,10 +159,10 @@ require([
} }
}); });
mainView.ui.add("akViewDiv", "bottom-left"); mainView.ui.add('akViewDiv', 'bottom-left');
const hiView = new MapView({ const hiView = new MapView({
container: "hiViewDiv", container: 'hiViewDiv',
map: map, map: map,
extent: { extent: {
xmin: -342537, xmin: -342537,
...@@ -194,13 +182,36 @@ require([ ...@@ -194,13 +182,36 @@ require([
} }
}); });
mainView.ui.add("hiViewDiv", "bottom-left"); mainView.ui.add('hiViewDiv', 'bottom-left');
// Create legend for layer to place in mainView.
const legend = new Legend({
view: mainView,
layerInfos: [
{
layer: layer,
title: 'Alerts and Opinions'
}
]
});
// Add legend to the mainView
mainView.ui.add(legend, 'bottom-right');
// Add Home button to mainView.
const homeButton = new Home({
view: mainView
});
// Add the home button to the top left corner of the view
mainView.ui.add(homeButton, 'top-left');
mainView mainView
.when(maintainFixedExtent) .when(maintainFixedExtent)
// .then(disableNavigation) // .then(disableNavigation)
.then(disablePopupOnClick) .then(disablePopupOnClick)
.then(enableHighlightOnPointerMove); .then(enableHighlightOnPointerMove)
.then(enableParameter1Selection)
.then(enableParameter2Selection)
.then(mainView.map = map);
akView akView
.when(disableNavigation) .when(disableNavigation)
.then(disablePopupOnClick) .then(disablePopupOnClick)
...@@ -210,11 +221,12 @@ require([ ...@@ -210,11 +221,12 @@ require([
.then(disablePopupOnClick) .then(disablePopupOnClick)
.then(enableHighlightOnPointerMove); .then(enableHighlightOnPointerMove);
function maintainFixedExtent(view) { function maintainFixedExtent(view) {
var fixedExtent = view.extent.clone(); var fixedExtent = view.extent.clone();
// keep a fixed extent in the view // keep a fixed extent in the view
// when the view size changes // when the view size changes
view.on("resize", function() { view.on('resize', function() {
view.extent = fixedExtent; view.extent = fixedExtent;
}); });
return view; return view;
...@@ -226,8 +238,8 @@ require([ ...@@ -226,8 +238,8 @@ require([
function enableHighlightOnPointerMove(view) { function enableHighlightOnPointerMove(view) {
view.whenLayerView(layer).then(function(layerView) { view.whenLayerView(layer).then(function(layerView) {
view.on("pointer-move", function(event) { view.on('pointer-move', function(event) {
// console.log("Highlight"); // console.log('Highlight');
view.hitTest(event).then(function(response) { view.hitTest(event).then(function(response) {
var lastHighlight = highlight; var lastHighlight = highlight;
...@@ -240,10 +252,9 @@ require([ ...@@ -240,10 +252,9 @@ require([
return result.graphic.layer === layer; return result.graphic.layer === layer;
})[0].graphic; })[0].graphic;
feature.popupTemplate = layer.popupTemplate; feature.popupTemplate = layer.popupTemplate;
id = feature.attributes.OBJECTID_1; id = feature.attributes.OBJECTID_12_13;
//Does hovering over a feature return it's ObjectID? // Log feature
console.log(feature); //console.log(feature);
//console.log(feature.attributes.OBJECTID); //This is coming up as undefined
highlight = layerView.highlight([id]); highlight = layerView.highlight([id]);
var selectionId = mainView.popup.selectedFeature var selectionId = mainView.popup.selectedFeature
? mainView.popup.selectedFeature.attributes.OBJECTID_1 ? mainView.popup.selectedFeature.attributes.OBJECTID_1
...@@ -287,23 +298,23 @@ require([ ...@@ -287,23 +298,23 @@ require([
view.navigation.mouseWheelZoomEnabled = false; view.navigation.mouseWheelZoomEnabled = false;
// disable zooming via double-click on the view // disable zooming via double-click on the view
view.on("double-click", stopEvtPropagation); view.on('double-click', stopEvtPropagation);
// disable zooming out via double-click + Control on the view // disable zooming out via double-click + Control on the view
view.on("double-click", ["Control"], stopEvtPropagation); view.on('double-click', ['Control'], stopEvtPropagation);
// disables pinch-zoom and panning on the view // disables pinch-zoom and panning on the view
view.navigation.browserTouchPanEnabled = false; view.navigation.browserTouchPanEnabled = false;
view.on("drag", stopEvtPropagation); view.on('drag', stopEvtPropagation);
// disable the view's zoom box to prevent the Shift + drag // disable the view's zoom box to prevent the Shift + drag
// and Shift + Control + drag zoom gestures. // and Shift + Control + drag zoom gestures.
view.on("drag", ["Shift"], stopEvtPropagation); view.on('drag', ['Shift'], stopEvtPropagation);
view.on("drag", ["Shift", "Control"], stopEvtPropagation); view.on('drag', ['Shift', 'Control'], stopEvtPropagation);
// prevents zooming and rotation with the indicated keys // prevents zooming and rotation with the indicated keys
view.on("key-down", function(event) { view.on('key-down', function(event) {
var prohibitedKeys = ["+", "-", "_", "=", "a", "d"]; var prohibitedKeys = ['+', '-', '_', '=', 'a', 'd'];
var keyPressed = event.key.toLowerCase(); var keyPressed = event.key.toLowerCase();
if (prohibitedKeys.indexOf(keyPressed) !== -1) { if (prohibitedKeys.indexOf(keyPressed) !== -1) {
event.stopPropagation(); event.stopPropagation();
...@@ -314,14 +325,138 @@ require([ ...@@ -314,14 +325,138 @@ require([
} }
// prevents the user from opening the popup with click // prevents the user from opening the popup with click
function disablePopupOnClick(view) { function disablePopupOnClick(view) {
view.on("click", function(event) { view.on('click', function(event) {
event.stopPropagation(); event.stopPropagation();
}); });
return view; return view;
} }
// Allows the user to pick the parameters to display.
function enableParameter1Selection(view) {
var selectNode = document.getElementById('parameter-1-select');
selectNode.addEventListener('change', function(event) {
console.log('Parameter 1 old selection:', parameter1 );
parameter1 = event.target.value;
console.log('Parameter 1 new selection:', parameter1 );
setRelationshipRenderer();
setPopupTemplate();
layer.popupTemplate = popupTemplate;
});
}
function enableParameter2Selection(view) {
var selectNode = document.getElementById('parameter-2-select');
selectNode.addEventListener('change', function(event) {
console.log('Parameter 2 old selection:', parameter2 );
parameter2 = event.target.value;
console.log('Parameter 2 new selection:', parameter2 );
setRelationshipRenderer();
setPopupTemplate();
layer.popupTemplate = popupTemplate;
});
}
// Create relationship (or bivariate) renderer.
function setRelationshipRenderer() {
const params = {
layer: layer,
view: mainView,
field1: {
field: parameter1
},
field2: {
field: parameter2
},
// Set orientation of legend to a diamond.
focus: 'HH',
// Number of classes for grid (i.e., 2 = 2x2 grid; value can also be 3 or 4)
numClasses: 2
};
// Apply renderer to layer.
relationshipRendererCreator.createRenderer(params).then(function(response) {
layer.renderer = response.renderer;
});
}
// Set the popup template
function setPopupTemplate() {
popupTemplate = {
title:'{CD_Code}',
content: [
{
type:'fields',
fieldInfos: [
{
fieldName: 'TotalPop',
label: 'Total Population'
},
{
fieldName: parameter1,
label: parameter1
},
{
fieldName: parameter2,
label: parameter2
}
]
}
]
}
};
// Set the options for the parameter select lists.
function setParameterSelectionLists() {
var parameter1options = {
// 'HT' : 'Heat Advisory', // Not enough data...
'FL' : 'Flood Advisory',
//'HU' : 'Hurricane Warning', // Not enough data...
//'RP' : 'Rip Current', // Not enough data...
'SV' : 'Severe Thunderstorm'
//'WS' : 'Winter Storm' // Not enough data...
};
var select = document.getElementById('parameter-1-select');
select.options.length = 0
for(index in parameter1options) {
select.options[select.options.length] = new Option(parameter1options[index], index);
}
var parameter2options = {
'happening' : 'Estimated percentage who think that global warming is happening',
'happeningOppose' : 'Estimated percentage who do not think that global warming is happening',
'congress' : 'Estimated percentage who think Congress should be doing more/much more to address global warming',
'congressOppose' : 'Estimated percentage who think Congress should be doing less/much less to address global warming',
'worried' : 'Estimated percentage who are somewhat/very worried about global warming',
'worriedOppose' : 'Estimated percentage who are not very/not at all worried about global warming'
};
var select = document.getElementById('parameter-2-select');
select.options.length = 0
for(index in parameter2options) {
select.options[select.options.length] = new Option(parameter2options[index], index);
}
console.log('Parameter selection lists set.')
}
// // add slider widget
// // Joe is adding a comment for some reason...
// const slider = new Slider({
// container: document.getElementById('sliderDiv'),
// min: 0,
// max: 100,
// values: [ 50 ],
// rangeLabelsVisible: true,
// precision: 0,
// layout: 'vertical'
// });
//
// mainView.ui.add(slider, {
// position: 'top-right',
// });