I am using the JavaScript API version 3.16 and I am developing an application that loads three scale dependent feature layers on a map. The layers are being added to the map after the data in a column in the layer is classified via the generateRendererTask. There are feature tables associated with each layer and the appropriate feature table is visible when the corresponding feature layer is shown on the map. I have a couple questions...
1. Thanks to the code from Robert Scheitlin, the feature table updates on zoom in. On zoom out, it does not update accurately. If I change the spatial relationship to "CONTAINS" it does. Is it correct to change that parameter?
2. When the second feature layer displays, the header of the table is correct, but not the actual table results. What method should I use? I tried featureTable.grid.setStore, but that did not work.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Feature Table Example For ESRI</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.16/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/css/esri.css">
<script src="https://js.arcgis.com/3.16/"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#map {
width: 100%;
height: 500px;
margin: 0;
padding: 0;
}
#divGrid {
position: absolute;
left: 0px;
top: 525px;
background-color: white;
z-index: 999;
overflow: scroll;
width: 100%;
height: 400px;
margin-bottom: 20px;
}
#citypoints {
position: absolute;
background-color: white;
z-index: 999;
overflow: scroll;
width: 100%;
height: 100%;
}
#citypolys {
position: absolute;
background-color: white;
z-index: 999;
overflow: scroll;
width: 100%;
height: 100%;
}
#tractpolys {
position: absolute;
background-color: white;
z-index: 999;
overflow: scroll;
width: 100%;
height: 100%;
}
.displaynone {
display: none;
}
#divShowHideTable {
position: absolute;
top: 317px;
left: 20px;
z-index: 50;
}
#imgHiddenTable:hover {
cursor: pointer;
}
#imgShownTable:hover {
cursor: pointer;
}
/*#divGrid {
position: absolute;
top: 500px;
width: 100%;
height: 40%;
}*/
</style>
<script>
// declare variables and instantiate some
var map, grid, fl_url, symbol, polygonSymbol, highlightSymbol, pointSymbol, outlineSymbol, line, renderer, featureLayer, loading, myFeatureTable, idx, title, content, drawingOptions, placeholdertxt, whereclause, fieldsToDisplay, selectionToolbar, val, fieldsoutputted, fieldsarray, lblgridheadertxt, citypointlayer, stateoutlinelayer, cityoutlinelayer, citypolygonlayer, tractpolygonlayer, citypointrenderer, stateoutlinerender, cityoutlinerenderer, citypolygonrenderer, tractpolygonrenderer, tb, citypointFT, citypolyFT, tractpolyFT, rfrshtbls, initld;
var visiblelayers = [],
symbolArray = [],
labelArray = [],
fieldsToSearch = [];
var renderedField = 'pop2000';
var DataUnavailableTxt = "Population < 50",
oldExtent = null;
// initialize modules and classes
require([
"esri/map"
, "esri/graphic"
, "esri/dijit/Basemap"
, "esri/dijit/BasemapLayer"
, "esri/dijit/BasemapGallery"
, "esri/arcgis/utils"
, "esri/urlUtils"
, "esri/geometry/webMercatorUtils"
, "esri/dijit/Search"
, "esri/layers/FeatureLayer"
, "esri/dijit/FeatureTable"
, "esri/geometry/Extent"
, "esri/geometry/Polygon"
, "esri/symbols/SimpleFillSymbol"
, "esri/layers/ArcGISDynamicMapServiceLayer"
, "esri/layers/ImageParameters"
, "esri/InfoTemplate"
, "esri/renderers/ClassBreaksRenderer"
, "esri/tasks/GenerateRendererParameters"
, "esri/tasks/GenerateRendererTask"
, "esri/tasks/ClassBreaksDefinition"
, "esri/symbols/SimpleMarkerSymbol"
, "esri/symbols/SimpleLineSymbol"
, "esri/renderers/SimpleRenderer"
, "esri/tasks/AlgorithmicColorRamp"
, "esri/lang"
, "dojo/_base/lang"
, "esri/toolbars/draw"
, "esri/geometry/Point"
, "esri/geometry/geometryEngine"
, "esri/dijit/Scalebar"
, "esri/layers/LayerDrawingOptions"
, "esri/request"
, "dojo/dom-construct"
, "esri/tasks/QueryTask"
, "esri/tasks/query"
, "esri/Color"
, "dijit/form/Slider"
, "dojo/dom-style"
, "dgrid/Selection"
, "dojo/ready"
, "dojo/on"
, "dojo/_base/array"
, "dojox/gfx"
, "esri/symbols/jsonUtils"
, "dojo/_base/array"
, "dojo/dom"
, "dijit/form/Button"
, "dojo/data/ItemFileReadStore"
, "dijit/registry"
, "dojo/parser"
, "dojo/_base/declare"
, "dijit/layout/BorderContainer"
, "dijit/layout/ContentPane"
, "dijit/form/TextBox"
, "dgrid/extensions/ColumnHider"
, "dojo/domReady!"
], function(
Map
, Graphic
, Basemap
, BasemapLayer
, BasemapGallery
, arcgisUtils
, urlUtils
, webMercatorUtils
, Search
, FeatureLayer
, FeatureTable
, Extent
, Polygon
, SimpleFillSymbol
, ArcGISDynamicMapServiceLayer
, ImageParameters
, InfoTemplate
, ClassBreaksRenderer
, GenerateRendererParameters
, GenerateRendererTask
, ClassBreaksDefinition
, SimpleMarkerSymbol
, SimpleLineSymbol
, SimpleRenderer
, AlgorithmicColorRamp
, esriLang
, lang
, Draw
, Point
, geometryEngine
, Scalebar
, LayerDrawingOptions
, esriRequest
, domConstruct
, QueryTask
, Query
, Color
, Slider
, domStyle
, Selection
, ready
, on
, arrayUtils
, gfx
, jsonUtils
, array
, dom
, Button
, ItemFileReadStore
, registry
, parser
, declare
, BorderContainer
, ContentPane
, TextBox
, ColumnHider
, ready
)
{
parser.parse();
var DynamicMapServiceURL = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer";
// define symbols
highlightSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 3)).setColor(new Color([125, 125, 125, 0.35]));
polygonSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
pointSymbol = new SimpleMarkerSymbol().setStyle(SimpleMarkerSymbol.STYLE_CIRCLE).setSize(8).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
outlineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 1);
// intial map extent
var initialExtent = new esri.geometry.Extent({
"xmin": -19525916.67711644,
"ymin": 1491562.5722065126,
"xmax": -2404022.3412415087,
"ymax": 9318714.26860648,
"spatialReference": {
"wkid": 102100
}
});
// instantiate infoTemplate
var infotemp = new InfoTemplate();
// define the dynamic map service layer and the image parameter attribute it uses
var imageParameters = new ImageParameters();
imageParameters.format = "png";
var dynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(DynamicMapServiceURL, {
"opacity": 1.0,
"imageParameters": imageParameters
});
// add a map to the page
map = new Map("map", {
//zoom: 4,
basemap: "gray",
extent: initialExtent
//,infoTemplate: infotemp
});
// events that fire, based on actions in the UI
// the function below displays an error message and hides the div in which the map is drawn
function showErr(err)
{
'use strict';
console.log("Error Details: ", err);
}
on(dom.byId("imgShownTable"), "click", function(e)
{
// hide the table
//ShowElement(e.id, 'divGrid', '', '');
$('#divGrid').hide();
// show the hidden Legend image and hide the shown Legend image
$('#divShownTable').hide();
$('#divHiddenTable').show();
});
on(dom.byId("imgHiddenTable"), "click", function(e)
{
// show the table
//ShowElement(e.id, 'divGrid', '', '');
$('#divGrid').show();
showHideGridAndLegend();
// hide the hidden Legend image and show the shown Legend image
$('#divShownTable').show();
$('#divHiddenTable').hide();
});
// set the initial visibility of the controls in the UI
function setInitialVisibilityOfControls()
{
'use strict';
// show buttons/controls
//$('#divHiddenLegend').show();
//$('#divHiddenOtherControls').show();
$('#divHiddenTable').show();
//$('#divDraw').show();
//// hide divs that contain controls
//$('#divLegend').hide();
//$('#divOtherControls').hide();
$('#divGrid').hide();
// make the controls draggable
//$("#divLegend").draggable({ containment: "#divMap", scroll: false });
//$('#divOtherControls').draggable({ containment: "#divMap", scroll: false });
//$('#divGrid').draggable({ containment: "#divMap", scroll: false });
}
// hide the mouse-over effect (infowindow and any graphics) when the cursor moves outside of the map extent
map.on("mouse-out", function(evt)
{
var loc = evt.mapPoint;
if (!map.extent.contains(loc))
{
map.infoWindow.hide();
map.graphics.clear();
}
});
// substitute the "(" and ", " in the CI values
map.infoWindow.on("show", function()
{
map.infoWindow.setContent(map.infoWindow._contentPane.innerHTML.replace(/\(|\)/g, '').replace(/, /g, ' - '));
});
// clear any graphics on the map when the infowindow hides/goes away
map.infoWindow.on("hide", function()
{
map.graphics.clear();
});
//create new FeatureTable and set its properties
function AddGrid(lyrid, gridloc)
{
'use strict';
var existingGrid = dijit.byId(gridloc);
if (existingGrid)
{
existingGrid.destroyRecursive(true);
}
if (lyrid === 3)
{
tractpolyFT = new FeatureTable({
"featureLayer": tractpolygonlayer,
"map": map,
"showStatistics": false,
"zoomToSelection": false,
"syncSelection": true,
"outFields": ["*"]
}, gridloc);
tractpolyFT.startup();
} else
{
if (lyrid === 0)
{
citypointFT = new FeatureTable({
"featureLayer": citypointlayer,
"map": map,
"showStatistics": false,
"zoomToSelection": false,
"syncSelection": true,
"outFields": ["*"]
}, gridloc);
citypointFT.startup();
} else
{
citypolyFT = new FeatureTable({
"featureLayer": citypolygonlayer,
"map": map,
"showStatistics": false,
"zoomToSelection": false,
"syncSelection": true,
"outFields": ["*"]
}, gridloc);
citypolyFT.startup();
}
}
}
// this is a custom function used to format fields in the feature table and popup
formatVal = function(val)
{
return val.replace(/\(|\)/g, '').replace(/, /g, ' - ');
}
// the 3 functions below are formatting functions, with their origins documented above them
//http://stackoverflow.com/questions/18082/validate-decimal-numbers-in-javascript-isnumeric?page=1&tab...
var isNumber = function(n)
{
return !isNaN(parseFloat(n)) && isFinite(n);
};
//http://james.padolsey.com/javascript/wordwrap-for-javascript/
function wordwrap(str, width, brk, cut)
{
'use strict';
brk = brk || '\n';
width = width || 75;
cut = cut || false;
if (!str)
{
return str;
}
var regex = '.{1,' + width + '}(\\s|$)' + (cut ? '|.{' + width + '}|.+$' : '|\\S+?(\\s|$)');
//this line will cause a JSLint error: Missing 'new' prefix when invoking a constructor (this error can be ignored)
return str.match(RegExp(regex, 'g')).join(brk);
}
function formatValues(num)
{
'use strict';
return number.format(num, {
"places": 1
});
}
// this function is a modification of the one just above
function formatValues2(num)
{
'use strict';
return num = num.toFixed(1);
}
// the functions below dynamically generate a renderer and apply that
// renderer generated by the createRenderer function above to the featureLayer and adds labels.
// using individual functions, as trying to use a generic/parameterized one before did not work
function applyctyptRenderer(citypointrenderer)
{
'use strict';
citypointrenderer.defaultLabel = DataUnavailableTxt;
citypointrenderer.defaultSymbol = pointSymbol;
citypointlayer.setRenderer(citypointrenderer);
citypointlayer.renderer.setOpacityInfo(0.7);
map.addLayer(citypointlayer);
}
function applystoutRenderer(stateoutlinerenderer)
{
'use strict';
stateoutlinerenderer.defaultLabel = DataUnavailableTxt;
stateoutlinerenderer.defaultSymbol = outlineSymbol;
stateoutlinelayer.setRenderer(stateoutlinerenderer);
map.addLayer(stateoutlinelayer);
}
function applyctyoutRenderer(cityoutlinerenderer)
{
'use strict';
cityoutlinerenderer.defaultLabel = DataUnavailableTxt;
cityoutlinerenderer.defaultSymbol = outlineSymbol;
cityoutlinelayer.setRenderer(cityoutlinerenderer);
map.addLayer(cityoutlinelayer);
}
function applyctypolyRenderer(citypolygonrenderer)
{
'use strict';
citypolygonrenderer.defaultLabel = DataUnavailableTxt;
citypolygonrenderer.defaultSymbol = polygonSymbol;
citypolygonlayer.setRenderer(citypolygonrenderer);
citypolygonlayer.renderer.setOpacityInfo(0.7);
map.addLayer(citypolygonlayer);
}
function applytrtpolyRenderer(tractpolygonrenderer)
{
'use strict';
tractpolygonrenderer.defaultLabel = DataUnavailableTxt;
tractpolygonrenderer.defaultSymbol = polygonSymbol;
tractpolygonlayer.setRenderer(tractpolygonrenderer);
tractpolygonlayer.renderer.setOpacityInfo(0.7);
map.addLayer(tractpolygonlayer);
}
function createRenderer(lyr, field)
{
'use strict';
var classDef = new ClassBreaksDefinition();
classDef.classificationField = field;
classDef.classificationMethod = $('#islClassifiers').val() ? $('#islClassifiers').val() : "natural-breaks";
classDef.breakCount = $('#islClassifiersCount').val() ? $('#islClassifiersCount').val() : 7;
switch (lyr)
{
case 0:
classDef.baseSymbol = pointSymbol;
break;
case 2:
classDef.baseSymbol = polygonSymbol;
break;
case 3:
classDef.baseSymbol = polygonSymbol;
break;
default:
classDef.baseSymbol = outlineSymbol;
break;
}
var colorRamp = new AlgorithmicColorRamp();
switch ($('#islColorScheme').val())
{
case 'OriginalBlue':
// original that we use on BRFSS
colorRamp.fromColor = new Color.fromHex("#F0F9E8");
colorRamp.toColor = new Color.fromHex("#2b8cbe");
break;
case 'Prevention':
// default color scheme for prevention
colorRamp.fromColor = new Color.fromHex("#ffffcc");
colorRamp.toColor = new Color.fromHex("#0c2c84");
break;
case 'UnhealthyBehaviors':
// default color scheme for unhealthy behaviors and healthy outcomes
colorRamp.fromColor = new Color.fromHex("#ffffd4");
colorRamp.toColor = new Color.fromHex("#8c2d04");
break;
case 'HealthyOutcomes':
// default color scheme for unhealthy behaviors and healthy outcomes
colorRamp.fromColor = new Color.fromHex("#ffffd4");
colorRamp.toColor = new Color.fromHex("#8c2d04");
break;
case 'Orange':
// another option -- orange-ish
colorRamp.fromColor = new Color.fromHex("#ffffe5");
colorRamp.toColor = new Color.fromHex("#662506");
break;
default:
// another option -- blue-ish
colorRamp.fromColor = new Color.fromHex("#ffffd9");
colorRamp.toColor = new Color.fromHex("#081d58");
break;
}
colorRamp.algorithm = "hsv";
classDef.colorRamp = colorRamp;
var params = new GenerateRendererParameters();
params.classificationDefinition = classDef;
params.where = whereclause;
var generateRenderer = new GenerateRendererTask(DynamicMapServiceURL + "/" + lyr);
// apply a different renderer, based on the layer
switch (lyr)
{
case 0:
generateRenderer.execute(params, applyctyptRenderer, showErr);
break;
case 2:
generateRenderer.execute(params, applyctypolyRenderer, showErr);
break;
case 3:
generateRenderer.execute(params, applytrtpolyRenderer, showErr);
break;
default:
break;
}
}
// show the attributes in a custom way
function showCustomIW(e, lyrid)
{
'use strict';
map.graphics.clear();
var graphic = e.graphic;
setIWTitleAndContent(lyrid);
map.infoWindow.setTitle(esriLang.substitute(graphic.attributes, infotemp.title));
map.infoWindow.setContent(esriLang.substitute(graphic.attributes, infotemp.content));
lyrid === '0' || lyrid === '2' ? map.infoWindow.resize(350, 250) : map.infoWindow.resize(350, 150);
var highlightGraphic = new Graphic(graphic.geometry, lyrid === '0' ? pointSymbol : polygonSymbol);
map.graphics.add(highlightGraphic);
map.infoWindow.show(e.screenPoint, map.getInfoWindowAnchor(e.screenPoint));
}
// hide the infowindow and any graphics
function hideInfoWindow()
{
'use strict';
map.graphics.clear();
map.infoWindow.hide();
}
// set title and content of infowindow
function setIWTitleAndContent(layerid)
{
'use strict';
map.infoWindow.hide();
title = "${areaname}";
content = "${*}";
infotemp.setTitle(title);
infotemp.setContent(content);
}
function LoadCityPointLayer()
{
'use strict';
//#region CityPointLayer
// add city point layer
citypointlayer = new FeatureLayer(DynamicMapServiceURL + "/0", {
mode: FeatureLayer.MODE_ONDEMAND,
outFields: ["*"],
//infoTemplate: infotemp,
id: "City Point Layer",
minScale: 0,
maxScale: 4622324
});
createRenderer(0, renderedField);
//citypointlayer.on("click", function(evt)
//{
// showCustomIW(evt, 0);
//});
//citypointlayer.on("mouse-over", function(evt)
//{
// showCustomIW(evt, 0);
//});
//citypointlayer.on("mouse-out", hideInfoWindow);
citypointlayer.on("selection-complete", function(e)
{
var results = [];
arrayUtils.forEach(e.features, function(feature)
{
results.push(feature.attributes.OBJECTID);
});
citypointFT.selectedRowIds = results;
citypointFT._showSelectedRecords();
citypointFT._gridTitleNode.innerHTML = citypointlayer.name + ' (' + (results.length != 'undefined' ? (results.length > 1 ? results.length + ' Features)' : 1 + ' Feature)') : "");
});
citypointlayer.on("selection-clear", function(e)
{
citypointlayer.setSelectionSymbol(null);
map.setExtent(map.extent);
});
AddGrid(0, "citypoints");
// limit the feature table to the records of the feature layer in the current map extent
// sort, as well
citypointlayer.on("load", function(evt)
{
citypointFT.grid.set('sort', [{
attribute: "NAME"
}]);
var extent = citypointlayer.fullExtent;
if (webMercatorUtils.canProject(extent, map))
{
map.on("extent-change", lang.hitch(this, function(params)
{
// do not highlight the features when the map extent changes, as can be seen from below...it triggers a selection
citypointlayer.setSelectionSymbol(null);
// taken from https://community.esri.com/thread/173929
var query = new Query();
query.geometry = params.extent;
query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
citypointlayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
}))
}
});
//#endregion
}
function LoadCityPolygonLayer()
{
'use strict';
//#region CityPolygonLayer
// add city polygon layer
citypolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/2", {
mode: FeatureLayer.MODE_ONDEMAND,
outFields: ["*"],
//infoTemplate: infotemp,
id: "City Polygon Layer",
minScale: 4622324,
maxScale: 1155581
});
createRenderer(2, renderedField);
//citypolygonlayer.on("click", function(evt)
//{
// showCustomIW(evt, 2);
//});
//citypolygonlayer.on("mouse-over", function(evt)
//{
// showCustomIW(evt, 2);
//});
//citypolygonlayer.on("mouse-out", hideInfoWindow);
citypolygonlayer.on("selection-complete", function(e)
{
var results = [];
arrayUtils.forEach(e.features, function(feature)
{
results.push(feature.attributes.OBJECTID);
});
citypolyFT.selectedRowIds = results;
citypolyFT._showSelectedRecords();
citypolyFT._gridTitleNode.innerHTML = citypolygonlayer.name + ' (' + (results.length != 'undefined' ? (results.length > 1 ? results.length + ' Features)' : 1 + ' Feature)') : "");
});
citypolygonlayer.on("selection-clear", function(e)
{
citypolygonlayer.setSelectionSymbol(null);
map.setExtent(map.extent);
});
AddGrid(2, "citypolys");
// limit the feature table to the records of the feature layer in the current map extent
// sort, as well
citypolygonlayer.on("load", function(evt)
{
citypolyFT.grid.set('sort', [{
attribute: "NAME"
}]);
var extent = citypolygonlayer.fullExtent;
if (webMercatorUtils.canProject(extent, map))
{
map.on("extent-change", lang.hitch(this, function(params)
{
// do not highlight the features when the map extent changes, as can be seen from below...it triggers a selection
citypolygonlayer.setSelectionSymbol(null);
// taken from https://community.esri.com/thread/173929
var query = new Query();
query.geometry = params.extent;
query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
citypolygonlayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
}))
}
});
//#endregion
}
function LoadTractPolygonLayer()
{
'use strict';
//#region TractPolygonLayer
// add census tract polygon layer
tractpolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/3", {
mode: FeatureLayer.MODE_ONDEMAND,
outFields: ["*"],
//infoTemplate: infotemp,
id: "Census Tract Polygon Layer",
minScale: 1155581,
maxScale: 0
});
createRenderer(3, renderedField);
//tractpolygonlayer.on("click", function(evt)
//{
// showCustomIW(evt, 3);
//});
//tractpolygonlayer.on("mouse-over", function(evt)
//{
// showCustomIW(evt, 3);
//});
//tractpolygonlayer.on("mouse-out", hideInfoWindow);
tractpolygonlayer.on("selection-complete", function(e)
{
var results = [];
arrayUtils.forEach(e.features, function(feature)
{
results.push(feature.attributes.OBJECTID);
});
tractpolyFT.selectedRowIds = results;
tractpolyFT._showSelectedRecords();
tractpolyFT._gridTitleNode.innerHTML = tractpolygonlayer.name + ' (' + (results.length != 'undefined' ? (results.length > 1 ? results.length + ' Features)' : 1 + ' Feature)') : "");
});
tractpolygonlayer.on("selection-clear", function(e)
{
tractpolygonlayer.setSelectionSymbol(null);
map.setExtent(map.extent);
});
AddGrid(3, "tractpolys");
// limit the feature table to the records of the feature layer in the current map extent
// sort, as well
tractpolygonlayer.on("load", function(evt)
{
tractpolyFT.grid.set('sort', [{
attribute: "plc_tract2010"
}]);
var extent = tractpolygonlayer.fullExtent;
if (webMercatorUtils.canProject(extent, map))
{
map.on("extent-change", lang.hitch(this, function(params)
{
// do not highlight the features when the map extent changes, as can be seen from below...it triggers a selection
tractpolygonlayer.setSelectionSymbol(null);
// taken from https://community.esri.com/thread/173929
var query = new Query();
query.geometry = params.extent;
query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
tractpolygonlayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
}))
}
});
//#endregion
}
// the function below shows/hides the appropriate feature table, based on the map scale
function showHideGridAndLegend()
{
'use strict';
//console.log(map.getScale());
switch (true)
{
case (map.getScale() >= 4622324):
$('#citypoints').show();
$('#citypolys').hide();
$('#tractpolys').hide();
// the feature table is sometimes not shown expanded when the window showing it opens
// a search online led me to a post that recommended re-sizing the table, after the window has been opened
// this is an attempt that only works occasionally, right now
if (citypointFT)
{
citypointFT.grid.resize();
}
break;
case (map.getScale() < 4622324 && map.getScale() > 1155581):
$('#citypoints').hide();
$('#citypolys').show();
$('#tractpolys').hide();
// the feature table is sometimes not shown expanded when the window showing it opens
// a search online led me to a post that recommended re-sizing the table, after the window has been opened
// this is an attempt that only works occasionally, right now
if (citypolyFT)
{
citypolyFT.grid.resize();
}
break;
case (map.getScale() <= 1155581):
$('#citypoints').hide();
$('#citypolys').hide();
$('#tractpolys').show();
// the feature table is sometimes not shown expanded when the window showing it opens
// a search online led me to a post that recommended re-sizing the table, after the window has been opened
// this is an attempt that only works occasionally, right now
if (tractpolyFT)
{
tractpolyFT.grid.resize();
}
break;
default:
$('#citypoints').hide();
$('#citypolys').hide();
$('#tractpolys').hide();
break;
}
}
// the function below zooms to the map extent of the results of a query
function getMapExtentOnZoom(result)
{
'use strict';
// without the delays in calling the functions below, the functionality was not consistent.
if (result.features[0] !== 'undefined' && typeof result.features[0] !== 'undefined')
{
setTimeout(function()
{
//map.setExtent(result.features[0].geometry.getExtent().expand(1.45));
map.setExtent(result.features[0].geometry.getExtent(), true);
}, 450);
} else
{
setTimeout(function()
{
map.setExtent(initialExtent, true);
}, 450);
}
//showHideGridAndLegend();
}
// the function below queries the feature layer, based on if the where clause has a value or not
// if it does not, it uses the current map extent/geometry to limit the feature layer query
function zoomToSelection()
{
'use strict';
var loc, idx;
// set the layer to use, based on the selected input controls --
// States for City data and City polygons for Census data
if ($('#islCities').val() !== 'undefined' && typeof $('#islCities').val() !== 'undefined')
{
loc = $('#islCities').val();
idx = 3;
} else
{
loc = $('#islStates').val() === '59' ? '1=1' : $('#islStates').val();
idx = 1;
}
if (typeof (loc) !== 'undefined' && loc.length > 1)
{
// define the field to query to get the extent to show on zoom To
var qryfield = loc;
// assigning the spatial reference here, once the map is already created
var qry = new Query();
qry.outSpatialReference = map.SpatialReference;
qry.returnGeometry = true;
if (idx === 3)
{
qry.where = "STPL_FIPS = '" + qryfield + "'";
} else
{
qry.where = "STATE = '" + qryfield + "'";
}
qry.where = qry.where.replace(/'/g, "QUOTE");
var qryTask = new QueryTask(DynamicMapServiceURL + "/" + idx);
qryTask.execute(qry, getMapExtentOnZoom, showErr);
}
}
// function that calls individual functions to load the layers and tables and zoom, if necessary
function LoadLayers()
{
'use strict';
//renderedField = $('#islMeasures option:selected').val() !== '' && typeof $('#islMeasures option:selected').val() !== 'undefined' ? $('#islMeasures option:selected').val() + "_CrudePrev" : 'BINGE_CrudePrev';
//CI = $('#islMeasures option:selected').val() !== '' && typeof $('#islMeasures option:selected').val() !== 'undefined' ? $('#islMeasures option:selected').val() + "_Crude95CI" : "BINGE_Crude95CI";
renderedField = 'pop2000';
LoadCityPointLayer();
LoadCityPolygonLayer();
LoadTractPolygonLayer();
//LoadStateOutlineAndCityBoundaryLayers();
// add drawing toolbox
//addDrawingTools();
}
// remove layers from the map
function RemoveLayers()
{
'use strict';
map.removeLayer(citypointlayer);
map.removeLayer(citypolygonlayer);
map.removeLayer(tractpolygonlayer);
//map.removeLayer(dynamicMapServiceLayer);
}
// load the feature layers when the map loads
map.on("load", function()
{
// add feature layers to the map and associated behaviors of feature layers
LoadLayers();
// set initil visibility of buttons/divs/etc.
setInitialVisibilityOfControls();
});
// determine which feature table to show when a user zooms
map.on("extent-change", showHideGridAndLegend);
});
</script>
</head>
<body class="claro esri">
<div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'" style="width:100%; height:100%;">
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center', splitter:true" style="height:50%">
<div id="map">
<div id="divShowHideTable">
<div id="divShownTable" class="displaynone">
<img alttext="Image that displays when the Feature Table is showing."
src="Shared.Images.table_selected.png"
id="imgShownTable"
tooltip="Hide Table" />
</div>
<div id="divHiddenTable" class="displaynone">
<img alttext="Image that displays when the Feature Table is hidden."
src="Shared.Images.table_default.png"
id="imgHiddenTable"
tooltip="Show Table" />
</div>
</div>
</div>
</div>
</div>
<div id="divGrid">
<div id="citypoints"></div>
<div id="citypolys"></div>
<div id="tractpolys"></div>
</div>
</body>
</html>
Any help is greatly appreciated. Thanks.
- Chris
Solved! Go to Solution.
Chris,
OK the way I was working around the FeatureTable filtering on extent does not work in all cases (when the OIDs and table rowIDs do not coincide). So you will have to use 3.18 of the API that fixes those issues:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Feature Table Example For ESRI</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.18/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.18/esri/css/esri.css">
<script src="https://js.arcgis.com/3.18/"></script>
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#map {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#citypoints,
#statepolys,
#countypolys {
background-color: white;
z-index: 50;
width: 100%;
height: 100%;
}
#divShowHideTable {
position: absolute;
top: 317px;
left: 20px;
z-index: 50;
}
#imgTable:hover {
cursor: pointer;
}
</style>
<script>
// declare variables and instantiate some
var map, grid, fl_url, symbol, polygonSymbol, highlightSymbol, pointSymbol, outlineSymbol, line, renderer, featureLayer, loading, myFeatureTable, idx, title, content, drawingOptions, placeholdertxt, whereclause, fieldsToDisplay,
selectionToolbar, val, fieldsoutputted, fieldsarray, lblgridheadertxt, citypointlayer, stateoutlinelayer, cityoutlinelayer, statepolygonlayer, countypolygonlayer, citypointrenderer, stateoutlinerender, cityoutlinerenderer,
statepolygonrenderer, countypolygonrenderer, tb, citypointFT, statepolyFT, countypolyFT, rfrshtbls, initld;
var visiblelayers = [],
symbolArray = [],
labelArray = [],
fieldsToSearch = [];
var renderedField = 'pop2000';
var DataUnavailableTxt = "Population < 50",
oldExtent = null;
// initialize modules and classes
require([
"esri/map", "esri/graphic", "esri/dijit/Basemap", "esri/dijit/BasemapLayer", "esri/dijit/BasemapGallery", "esri/arcgis/utils", "esri/urlUtils", "esri/geometry/webMercatorUtils", "esri/dijit/Search", "esri/layers/FeatureLayer",
"esri/dijit/FeatureTable", "esri/geometry/Extent", "esri/geometry/Polygon", "esri/symbols/SimpleFillSymbol", "esri/layers/ArcGISDynamicMapServiceLayer", "esri/layers/ImageParameters", "esri/InfoTemplate",
"esri/renderers/ClassBreaksRenderer", "esri/tasks/GenerateRendererParameters", "esri/tasks/GenerateRendererTask", "esri/tasks/ClassBreaksDefinition", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
"esri/renderers/SimpleRenderer", "esri/tasks/AlgorithmicColorRamp", "esri/lang", "dojo/_base/lang", "esri/toolbars/draw", "esri/geometry/Point", "esri/geometry/geometryEngine", "esri/dijit/Scalebar", "esri/SpatialReference",
"esri/layers/LayerDrawingOptions", "esri/request", "dojo/dom-construct", "esri/tasks/QueryTask", "esri/tasks/query", "esri/Color", "dijit/form/Slider", "dojo/dom-style", "dgrid/Selection", "dojo/on", "esri/domUtils",
"dojo/_base/array", "dojox/gfx", "esri/symbols/jsonUtils", "dojo/dom", "dijit/form/Button", "dojo/data/ItemFileReadStore", "dijit/registry", "dojo/parser", "dojo/_base/declare", "dijit/layout/BorderContainer",
"dijit/layout/ContentPane", "dijit/form/TextBox", "dgrid/extensions/ColumnHider", "dojo/domReady!"
], function(
Map, Graphic, Basemap, BasemapLayer, BasemapGallery, arcgisUtils, urlUtils, webMercatorUtils, Search, FeatureLayer,
FeatureTable, Extent, Polygon, SimpleFillSymbol, ArcGISDynamicMapServiceLayer, ImageParameters, InfoTemplate,
ClassBreaksRenderer, GenerateRendererParameters, GenerateRendererTask, ClassBreaksDefinition, SimpleMarkerSymbol, SimpleLineSymbol,
SimpleRenderer, AlgorithmicColorRamp, esriLang, lang, Draw, Point, geometryEngine, Scalebar, SpatialReference,
LayerDrawingOptions, esriRequest, domConstruct, QueryTask, Query, Color, Slider, domStyle, Selection, on, domUtils,
arrayUtils, gfx, jsonUtils, dom, Button, ItemFileReadStore, registry, parser, declare, BorderContainer,
ContentPane, TextBox, ColumnHider
) {
parser.parse();
var DynamicMapServiceURL = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer";
// define symbols
highlightSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 3)).setColor(new Color([125, 125, 125, 0.35]));
polygonSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
pointSymbol = new SimpleMarkerSymbol().setStyle(SimpleMarkerSymbol.STYLE_CIRCLE).setSize(8).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
outlineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 1);
// intial map extent
var initialExtent = new esri.geometry.Extent({
"xmin": -19525916.67711644,
"ymin": 1491562.5722065126,
"xmax": -2404022.3412415087,
"ymax": 9318714.26860648,
"spatialReference": {
"wkid": 102100
}
});
// instantiate infoTemplate
var infotemp = new InfoTemplate();
// define the dynamic map service layer and the image parameter attribute it uses
var imageParameters = new ImageParameters();
imageParameters.format = "png";
var dynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(DynamicMapServiceURL, {
"opacity": 1.0,
"imageParameters": imageParameters
});
// add a map to the page
map = new Map("map", {
basemap: "gray",
extent: initialExtent
});
// events that fire, based on actions in the UI
// the function below displays an error message and hides the div in which the map is drawn
function showErr(err) {
console.log("Error Details: ", err);
}
on(dom.byId("imgTable"), "click", function(e) {
toggle_visibility();
});
function toggle_visibility() {
var appLayout = registry.byId("allContent");
var bottPanel = registry.byId("divGrid");
domUtils.toggle(bottPanel);
appLayout.resize();
}
// set the initial visibility of the controls in the UI
function setInitialVisibilityOfControls() {
domUtils.show(dom.byId('divHiddenTable'));
var appLayout = registry.byId("allContent");
var bottPanel = registry.byId("divGrid");
domUtils.hide(bottPanel);
appLayout.resize();
}
//create new FeatureTable and set its properties
function AddGrid(lyrid, gridloc) {
var existingGrid = registry.byId(gridloc);
if (existingGrid) {
existingGrid.destroyRecursive(true);
}
switch(lyrid){
case 0: {
citypointFT = new FeatureTable({
"featureLayer": citypointlayer,
"map": map,
"showStatistics": false,
"zoomToSelection": false,
"syncSelection": true,
"outFields": ["*"]
}, gridloc);
citypointFT.startup();
citypointFT.sort("areaname", false);
break;
}
case 2: {
statepolyFT = new FeatureTable({
"featureLayer": statepolygonlayer,
"map": map,
"showStatistics": false,
"zoomToSelection": false,
"syncSelection": true,
"outFields": ["*"]
}, gridloc);
statepolyFT.startup();
statepolyFT.sort("state_name", false);
break;
}
case 3: {
countypolyFT = new FeatureTable({
"featureLayer": countypolygonlayer,
"map": map,
"showStatistics": false,
"zoomToSelection": false,
"syncSelection": true,
"outFields": ["*"]
}, gridloc);
countypolyFT.startup();
countypolyFT.sort("areaname", false);
break;
}
}
}
// the functions below dynamically generate a renderer and apply that
// renderer generated by the createRenderer function above to the featureLayer and adds labels.
// using individual functions, as trying to use a generic/parameterized one before did not work
function applyctyptRenderer(citypointrenderer) {
citypointrenderer.defaultLabel = DataUnavailableTxt;
citypointrenderer.defaultSymbol = pointSymbol;
citypointlayer.setRenderer(citypointrenderer);
citypointlayer.renderer.setOpacityInfo(0.7);
map.addLayer(citypointlayer);
}
function applyctypolyRenderer(statepolygonrenderer) {
statepolygonrenderer.defaultLabel = DataUnavailableTxt;
statepolygonrenderer.defaultSymbol = polygonSymbol;
statepolygonlayer.setRenderer(statepolygonrenderer);
statepolygonlayer.renderer.setOpacityInfo(0.7);
map.addLayer(statepolygonlayer);
}
function applytrtpolyRenderer(countypolygonrenderer) {
countypolygonrenderer.defaultLabel = DataUnavailableTxt;
countypolygonrenderer.defaultSymbol = polygonSymbol;
countypolygonlayer.setRenderer(countypolygonrenderer);
countypolygonlayer.renderer.setOpacityInfo(0.7);
map.addLayer(countypolygonlayer);
}
function createRenderer(lyr, field) {
var classDef = new ClassBreaksDefinition();
classDef.classificationField = field;
classDef.classificationMethod = "natural-breaks";
classDef.breakCount = 7;
switch (lyr) {
case 0:
classDef.baseSymbol = pointSymbol;
break;
case 2:
classDef.baseSymbol = polygonSymbol;
break;
case 3:
classDef.baseSymbol = polygonSymbol;
break;
default:
classDef.baseSymbol = outlineSymbol;
break;
}
var colorRamp = new AlgorithmicColorRamp();
colorRamp.fromColor = new Color.fromHex("#ffffd9");
colorRamp.toColor = new Color.fromHex("#081d58");
colorRamp.algorithm = "hsv";
classDef.colorRamp = colorRamp;
var params = new GenerateRendererParameters();
params.classificationDefinition = classDef;
params.where = whereclause;
var generateRenderer = new GenerateRendererTask(DynamicMapServiceURL + "/" + lyr);
// apply a different renderer, based on the layer
switch (lyr) {
case 0:
generateRenderer.execute(params, applyctyptRenderer, showErr);
break;
case 2:
generateRenderer.execute(params, applyctypolyRenderer, showErr);
break;
case 3:
generateRenderer.execute(params, applytrtpolyRenderer, showErr);
break;
default:
break;
}
}
function LoadCityPointLayer() {
//#region CityPointLayer
// add city point layer
citypointlayer = new FeatureLayer(DynamicMapServiceURL + "/0", {
mode: FeatureLayer.MODE_ONDEMAND,
outFields: ["*"],
id: "City Point Layer",
minScale: 0,
maxScale: 4622324
});
AddGrid(0, "citypoints");
createRenderer(0, renderedField);
//#endregion
}
function LoadStatePolygonLayer() {
//#region StatePolygonLayer
// add state polygon layer
statepolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/2", {
mode: FeatureLayer.MODE_ONDEMAND,
outFields: ["*"],
id: "State Polygon Layer",
minScale: 4622324,
maxScale: 1155581
});
createRenderer(2, renderedField);
AddGrid(2, "statepolys");
//#endregion
}
function Loadcountypolygonlayer() {
//#region countypolygonlayer
// add county polygon layer
countypolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/3", {
mode: FeatureLayer.MODE_ONDEMAND,
outFields: ["*"],
id: "County Polygon Layer",
minScale: 1155581,
maxScale: 0
});
createRenderer(3, renderedField);
AddGrid(3, "countypolys");
//#endregion
}
// the function below shows/hides the appropriate feature table, based on the map scale
function showHideGridAndLegend(params) {
var query = new Query();
if(countypolygonlayer && countypolygonlayer.visibleAtMapScale){
domUtils.hide(registry.byId('citypoints'));
domUtils.hide(registry.byId('statepolys'));
domUtils.show(registry.byId('countypolys'));
query.geometry = webMercatorUtils.project(params.extent, new SpatialReference({wkid:4326}));
query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
countypolygonlayer.queryIds(query, lang.hitch(this, function(objectIds) {
countypolyFT.filterRecordsByIds(objectIds);
//countypolyFT._showSelectedRecords();
//countypolyFT._gridTitleNode.innerHTML = countypolygonlayer.name + ' (' + (objectIds.length != 'undefined' ? (objectIds.length > 1 ? objectIds.length + ' Features)' : 1 + ' Feature)') : "");
countypolyFT.resize();
}));
}else if(statepolygonlayer && statepolygonlayer.visibleAtMapScale){
domUtils.hide(registry.byId('citypoints'));
domUtils.show(registry.byId('statepolys'));
domUtils.hide(registry.byId('countypolys'));
query.geometry = webMercatorUtils.project(params.extent, new SpatialReference({wkid:4326}));
query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
statepolygonlayer.queryIds(query, lang.hitch(this, function(objectIds) {
statepolyFT.filterRecordsByIds(objectIds);
//statepolyFT._showSelectedRecords();
//statepolyFT._gridTitleNode.innerHTML = statepolygonlayer.name + ' (' + (objectIds.length != 'undefined' ? (objectIds.length > 1 ? objectIds.length + ' Features)' : 1 + ' Feature)') : "");
statepolyFT.resize();
}));
}else if(citypointlayer && citypointlayer.visibleAtMapScale){
domUtils.show(registry.byId('citypoints'));
domUtils.hide(registry.byId('statepolys'));
domUtils.hide(registry.byId('countypolys'));
query.geometry = webMercatorUtils.project(params.extent, new SpatialReference({wkid:4326}));
query.spatialRelationship = Query.SPATIAL_REL_CONTAINS;
citypointlayer.queryIds(query, lang.hitch(this, function(objectIds) {
citypointFT.filterRecordsByIds(objectIds);
//citypointFT._showSelectedRecords();
//citypointFT._gridTitleNode.innerHTML = citypointlayer.name + ' (' + (objectIds.length != 'undefined' ? (objectIds.length > 1 ? objectIds.length + ' Features)' : 1 + ' Feature)') : "");
citypointFT.resize();
citypointFT.refresh();
}));
}
}
// function that calls individual functions to load the layers and tables and zoom, if necessary
function LoadLayers() {
renderedField = 'pop2000';
LoadCityPointLayer();
LoadStatePolygonLayer();
Loadcountypolygonlayer();
}
// load the feature layers when the map loads
map.on("load", function() {
// add feature layers to the map and associated behaviors of feature layers
LoadLayers();
// set initil visibility of buttons/divs/etc.
setInitialVisibilityOfControls();
});
// determine which feature table to show when a user zooms
map.on("extent-change", showHideGridAndLegend);
});
</script>
</head>
<body class="claro esri">
<div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'" style="width:100%; height:100%;" id="allContent">
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center', splitter:true" style="height:50%">
<div id="map">
<div id="divShowHideTable">
<div id="divShownTable">
<img alttext="Image that displays when the Feature Table is showing." src="images/SelectRelatedRecords16.png" id="imgTable" tooltip="Show/Hide Table" />
</div>
</div>
</div>
</div>
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'bottom', splitter:true" style="height:50%" id="divGrid">
<div id="citypoints"></div>
<div id="statepolys"></div>
<div id="countypolys"></div>
</div>
</div>
</body>
</html>
Chris,
See if this is more of what you are after (I dropped jQuery and lots of code that was not needed):
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Feature Table Example For ESRI</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.16/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/css/esri.css">
<script src="https://js.arcgis.com/3.16/"></script>
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#map {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#citypoints,
#statepolys,
#tractpolys {
background-color: white;
z-index: 50;
width: 100%;
height: 100%;
}
#divShowHideTable {
position: absolute;
top: 317px;
left: 20px;
z-index: 50;
}
#imgTable:hover {
cursor: pointer;
}
</style>
<script>
// declare variables and instantiate some
var map, grid, fl_url, symbol, polygonSymbol, highlightSymbol, pointSymbol, outlineSymbol, line, renderer, featureLayer, loading, myFeatureTable, idx, title, content, drawingOptions, placeholdertxt, whereclause, fieldsToDisplay,
selectionToolbar, val, fieldsoutputted, fieldsarray, lblgridheadertxt, citypointlayer, stateoutlinelayer, cityoutlinelayer, statepolygonlayer, tractpolygonlayer, citypointrenderer, stateoutlinerender, cityoutlinerenderer,
statepolygonrenderer, tractpolygonrenderer, tb, citypointFT, statepolyFT, tractpolyFT, rfrshtbls, initld;
var visiblelayers = [],
symbolArray = [],
labelArray = [],
fieldsToSearch = [];
var renderedField = 'pop2000';
var DataUnavailableTxt = "Population < 50",
oldExtent = null;
// initialize modules and classes
require([
"esri/map", "esri/graphic", "esri/dijit/Basemap", "esri/dijit/BasemapLayer", "esri/dijit/BasemapGallery", "esri/arcgis/utils", "esri/urlUtils", "esri/geometry/webMercatorUtils", "esri/dijit/Search", "esri/layers/FeatureLayer",
"esri/dijit/FeatureTable", "esri/geometry/Extent", "esri/geometry/Polygon", "esri/symbols/SimpleFillSymbol", "esri/layers/ArcGISDynamicMapServiceLayer", "esri/layers/ImageParameters", "esri/InfoTemplate",
"esri/renderers/ClassBreaksRenderer", "esri/tasks/GenerateRendererParameters", "esri/tasks/GenerateRendererTask", "esri/tasks/ClassBreaksDefinition", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
"esri/renderers/SimpleRenderer", "esri/tasks/AlgorithmicColorRamp", "esri/lang", "dojo/_base/lang", "esri/toolbars/draw", "esri/geometry/Point", "esri/geometry/geometryEngine", "esri/dijit/Scalebar",
"esri/layers/LayerDrawingOptions", "esri/request", "dojo/dom-construct", "esri/tasks/QueryTask", "esri/tasks/query", "esri/Color", "dijit/form/Slider", "dojo/dom-style", "dgrid/Selection", "dojo/on", "esri/domUtils",
"dojo/_base/array", "dojox/gfx", "esri/symbols/jsonUtils", "dojo/dom", "dijit/form/Button", "dojo/data/ItemFileReadStore", "dijit/registry", "dojo/parser", "dojo/_base/declare", "dijit/layout/BorderContainer",
"dijit/layout/ContentPane", "dijit/form/TextBox", "dgrid/extensions/ColumnHider", "dojo/domReady!"
], function(
Map, Graphic, Basemap, BasemapLayer, BasemapGallery, arcgisUtils, urlUtils, webMercatorUtils, Search, FeatureLayer,
FeatureTable, Extent, Polygon, SimpleFillSymbol, ArcGISDynamicMapServiceLayer, ImageParameters, InfoTemplate,
ClassBreaksRenderer, GenerateRendererParameters, GenerateRendererTask, ClassBreaksDefinition, SimpleMarkerSymbol, SimpleLineSymbol,
SimpleRenderer, AlgorithmicColorRamp, esriLang, lang, Draw, Point, geometryEngine, Scalebar,
LayerDrawingOptions, esriRequest, domConstruct, QueryTask, Query, Color, Slider, domStyle, Selection, on, domUtils,
arrayUtils, gfx, jsonUtils, dom, Button, ItemFileReadStore, registry, parser, declare, BorderContainer,
ContentPane, TextBox, ColumnHider
) {
parser.parse();
var DynamicMapServiceURL = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer";
// define symbols
highlightSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 3)).setColor(new Color([125, 125, 125, 0.35]));
polygonSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
pointSymbol = new SimpleMarkerSymbol().setStyle(SimpleMarkerSymbol.STYLE_CIRCLE).setSize(8).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
outlineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 1);
// intial map extent
var initialExtent = new esri.geometry.Extent({
"xmin": -19525916.67711644,
"ymin": 1491562.5722065126,
"xmax": -2404022.3412415087,
"ymax": 9318714.26860648,
"spatialReference": {
"wkid": 102100
}
});
// instantiate infoTemplate
var infotemp = new InfoTemplate();
// define the dynamic map service layer and the image parameter attribute it uses
var imageParameters = new ImageParameters();
imageParameters.format = "png";
var dynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(DynamicMapServiceURL, {
"opacity": 1.0,
"imageParameters": imageParameters
});
// add a map to the page
map = new Map("map", {
basemap: "gray",
extent: initialExtent
});
// events that fire, based on actions in the UI
// the function below displays an error message and hides the div in which the map is drawn
function showErr(err) {
console.log("Error Details: ", err);
}
on(dom.byId("imgTable"), "click", function(e) {
toggle_visibility();
});
function toggle_visibility() {
var appLayout = registry.byId("allContent");
var bottPanel = registry.byId("divGrid");
domUtils.toggle(bottPanel);
appLayout.resize();
}
// set the initial visibility of the controls in the UI
function setInitialVisibilityOfControls() {
domUtils.show(dom.byId('divHiddenTable'));
var appLayout = registry.byId("allContent");
var bottPanel = registry.byId("divGrid");
domUtils.hide(bottPanel);
appLayout.resize();
}
// hide the mouse-over effect (infowindow and any graphics) when the cursor moves outside of the map extent
map.on("mouse-out", function(evt) {
var loc = evt.mapPoint;
if (!map.extent.contains(loc)) {
map.infoWindow.hide();
if(map.graphics){
map.graphics.clear();
}
}
});
// substitute the "(" and ", " in the CI values
map.infoWindow.on("show", function() {
map.infoWindow.setContent(map.infoWindow._contentPane.innerHTML.replace(/\(|\)/g, '').replace(/, /g, ' - '));
});
// clear any graphics on the map when the infowindow hides/goes away
map.infoWindow.on("hide", function() {
map.graphics.clear();
});
//create new FeatureTable and set its properties
function AddGrid(lyrid, gridloc) {
var existingGrid = registry.byId(gridloc);
if (existingGrid) {
existingGrid.destroyRecursive(true);
}
switch(lyrid){
case 0: {
citypointFT = new FeatureTable({
"featureLayer": citypointlayer,
"map": map,
"showStatistics": false,
"zoomToSelection": false,
"syncSelection": true,
"outFields": ["*"]
}, gridloc);
citypointFT.startup();
break;
}
case 2: {
statepolyFT = new FeatureTable({
"featureLayer": statepolygonlayer,
"map": map,
"showStatistics": false,
"zoomToSelection": false,
"syncSelection": true,
"outFields": ["*"]
}, gridloc);
statepolyFT.startup();
break;
}
case 3: {
tractpolyFT = new FeatureTable({
"featureLayer": tractpolygonlayer,
"map": map,
"showStatistics": false,
"zoomToSelection": false,
"syncSelection": true,
"outFields": ["*"]
}, gridloc);
tractpolyFT.startup();
break;
}
}
}
// this is a custom function used to format fields in the feature table and popup
formatVal = function(val) {
return val.replace(/\(|\)/g, '').replace(/, /g, ' - ');
}
// the 3 functions below are formatting functions, with their origins documented above them
//http://stackoverflow.com/questions/18082/validate-decimal-numbers-in-javascript-isnumeric?page=1&tab...
var isNumber = function(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
};
//http://james.padolsey.com/javascript/wordwrap-for-javascript/
function wordwrap(str, width, brk, cut) {
brk = brk || '\n';
width = width || 75;
cut = cut || false;
if (!str) {
return str;
}
var regex = '.{1,' + width + '}(\\s|$)' + (cut ? '|.{' + width + '}|.+$' : '|\\S+?(\\s|$)');
//this line will cause a JSLint error: Missing 'new' prefix when invoking a constructor (this error can be ignored)
return str.match(RegExp(regex, 'g')).join(brk);
}
function formatValues(num) {
return number.format(num, {
"places": 1
});
}
// this function is a modification of the one just above
function formatValues2(num) {
return num = num.toFixed(1);
}
// the functions below dynamically generate a renderer and apply that
// renderer generated by the createRenderer function above to the featureLayer and adds labels.
// using individual functions, as trying to use a generic/parameterized one before did not work
function applyctyptRenderer(citypointrenderer) {
citypointrenderer.defaultLabel = DataUnavailableTxt;
citypointrenderer.defaultSymbol = pointSymbol;
citypointlayer.setRenderer(citypointrenderer);
citypointlayer.renderer.setOpacityInfo(0.7);
map.addLayer(citypointlayer);
}
function applystoutRenderer(stateoutlinerenderer) {
stateoutlinerenderer.defaultLabel = DataUnavailableTxt;
stateoutlinerenderer.defaultSymbol = outlineSymbol;
stateoutlinelayer.setRenderer(stateoutlinerenderer);
map.addLayer(stateoutlinelayer);
}
function applyctyoutRenderer(cityoutlinerenderer) {
cityoutlinerenderer.defaultLabel = DataUnavailableTxt;
cityoutlinerenderer.defaultSymbol = outlineSymbol;
cityoutlinelayer.setRenderer(cityoutlinerenderer);
map.addLayer(cityoutlinelayer);
}
function applyctypolyRenderer(statepolygonrenderer) {
statepolygonrenderer.defaultLabel = DataUnavailableTxt;
statepolygonrenderer.defaultSymbol = polygonSymbol;
statepolygonlayer.setRenderer(statepolygonrenderer);
statepolygonlayer.renderer.setOpacityInfo(0.7);
map.addLayer(statepolygonlayer);
}
function applytrtpolyRenderer(tractpolygonrenderer) {
tractpolygonrenderer.defaultLabel = DataUnavailableTxt;
tractpolygonrenderer.defaultSymbol = polygonSymbol;
tractpolygonlayer.setRenderer(tractpolygonrenderer);
tractpolygonlayer.renderer.setOpacityInfo(0.7);
map.addLayer(tractpolygonlayer);
}
function createRenderer(lyr, field) {
var classDef = new ClassBreaksDefinition();
classDef.classificationField = field;
classDef.classificationMethod = "natural-breaks";
classDef.breakCount = 7;
switch (lyr) {
case 0:
classDef.baseSymbol = pointSymbol;
break;
case 2:
classDef.baseSymbol = polygonSymbol;
break;
case 3:
classDef.baseSymbol = polygonSymbol;
break;
default:
classDef.baseSymbol = outlineSymbol;
break;
}
var colorRamp = new AlgorithmicColorRamp();
colorRamp.fromColor = new Color.fromHex("#ffffd9");
colorRamp.toColor = new Color.fromHex("#081d58");
colorRamp.algorithm = "hsv";
classDef.colorRamp = colorRamp;
var params = new GenerateRendererParameters();
params.classificationDefinition = classDef;
params.where = whereclause;
var generateRenderer = new GenerateRendererTask(DynamicMapServiceURL + "/" + lyr);
// apply a different renderer, based on the layer
switch (lyr) {
case 0:
generateRenderer.execute(params, applyctyptRenderer, showErr);
break;
case 2:
generateRenderer.execute(params, applyctypolyRenderer, showErr);
break;
case 3:
generateRenderer.execute(params, applytrtpolyRenderer, showErr);
break;
default:
break;
}
}
// show the attributes in a custom way
function showCustomIW(e, lyrid) {
map.graphics.clear();
var graphic = e.graphic;
setIWTitleAndContent(lyrid);
map.infoWindow.setTitle(esriLang.substitute(graphic.attributes, infotemp.title));
map.infoWindow.setContent(esriLang.substitute(graphic.attributes, infotemp.content));
lyrid === '0' || lyrid === '2' ? map.infoWindow.resize(350, 250) : map.infoWindow.resize(350, 150);
var highlightGraphic = new Graphic(graphic.geometry, lyrid === '0' ? pointSymbol : polygonSymbol);
map.graphics.add(highlightGraphic);
map.infoWindow.show(e.screenPoint, map.getInfoWindowAnchor(e.screenPoint));
}
// hide the infowindow and any graphics
function hideInfoWindow() {
map.graphics.clear();
map.infoWindow.hide();
}
// set title and content of infowindow
function setIWTitleAndContent(layerid) {
map.infoWindow.hide();
title = "${areaname}";
content = "${*}";
infotemp.setTitle(title);
infotemp.setContent(content);
}
function LoadCityPointLayer() {
//#region CityPointLayer
// add city point layer
citypointlayer = new FeatureLayer(DynamicMapServiceURL + "/0", {
mode: FeatureLayer.MODE_ONDEMAND,
outFields: ["*"],
id: "City Point Layer",
minScale: 0,
maxScale: 4622324
});
createRenderer(0, renderedField);
citypointlayer.on("selection-complete", function(e) {
var results = [];
arrayUtils.forEach(e.features, function(feature) {
results.push(feature.attributes[citypointlayer.objectIdField]);
});
citypointFT.selectedRowIds = results;
citypointFT._showSelectedRecords();
citypointFT._gridTitleNode.innerHTML = citypointlayer.name + ' (' + (results.length != 'undefined' ? (results.length > 1 ? results.length + ' Features)' : 1 + ' Feature)') : "");
citypointFT.resize();
});
citypointlayer.on("selection-clear", function(e) {
citypointlayer.setSelectionSymbol(null);
map.setExtent(map.extent);
});
AddGrid(0, "citypoints");
// limit the feature table to the records of the feature layer in the current map extent
// sort, as well
citypointlayer.on("load", function(evt) {
citypointFT.grid.set('sort', [{
attribute: "NAME"
}]);
var extent = citypointlayer.fullExtent;
if (webMercatorUtils.canProject(extent, map)) {
map.on("extent-change", lang.hitch(this, function(params) {
// do not highlight the features when the map extent changes, as can be seen from below...it triggers a selection
citypointlayer.setSelectionSymbol(null);
// taken from https://community.esri.com/thread/173929
var query = new Query();
query.geometry = params.extent;
query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
citypointlayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
}))
}
});
//#endregion
}
function LoadStatePolygonLayer() {
//#region StatePolygonLayer
// add state polygon layer
statepolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/2", {
mode: FeatureLayer.MODE_ONDEMAND,
outFields: ["*"],
id: "State Polygon Layer",
minScale: 4622324,
maxScale: 1155581
});
createRenderer(2, renderedField);
statepolygonlayer.on("selection-complete", function(e) {
var results = [];
arrayUtils.forEach(e.features, function(feature) {
results.push(feature.attributes[statepolygonlayer.objectIdField]);
});
statepolyFT.selectedRowIds = results;
statepolyFT._showSelectedRecords();
statepolyFT._gridTitleNode.innerHTML = statepolygonlayer.name + ' (' + (results.length != 'undefined' ? (results.length > 1 ? results.length + ' Features)' : 1 + ' Feature)') : "");
statepolyFT.resize();
});
statepolygonlayer.on("selection-clear", function(e) {
statepolygonlayer.setSelectionSymbol(null);
map.setExtent(map.extent);
});
AddGrid(2, "statepolys");
// limit the feature table to the records of the feature layer in the current map extent
// sort, as well
statepolygonlayer.on("load", function(evt) {
statepolyFT.grid.set('sort', [{
attribute: "state_name"
}]);
var extent = statepolygonlayer.fullExtent;
if (webMercatorUtils.canProject(extent, map)) {
map.on("extent-change", lang.hitch(this, function(params) {
// do not highlight the features when the map extent changes, as can be seen from below...it triggers a selection
statepolygonlayer.setSelectionSymbol(null);
// taken from https://community.esri.com/thread/173929
var query = new Query();
query.geometry = params.extent;
query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
statepolygonlayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
}))
}
});
//#endregion
}
function LoadTractPolygonLayer() {
//#region TractPolygonLayer
// add census tract polygon layer
tractpolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/3", {
mode: FeatureLayer.MODE_ONDEMAND,
outFields: ["*"],
id: "Census Tract Polygon Layer",
minScale: 1155581,
maxScale: 0
});
createRenderer(3, renderedField);
tractpolygonlayer.on("selection-complete", function(e) {
var results = [];
arrayUtils.forEach(e.features, function(feature) {
results.push(feature.attributes[tractpolygonlayer.objectIdField]);
});
tractpolyFT.selectedRowIds = results;
tractpolyFT._showSelectedRecords();
tractpolyFT._gridTitleNode.innerHTML = tractpolygonlayer.name + ' (' + (results.length != 'undefined' ? (results.length > 1 ? results.length + ' Features)' : 1 + ' Feature)') : "");
tractpolyFT.resize();
});
tractpolygonlayer.on("selection-clear", function(e) {
tractpolygonlayer.setSelectionSymbol(null);
map.setExtent(map.extent);
});
AddGrid(3, "tractpolys");
// limit the feature table to the records of the feature layer in the current map extent
// sort, as well
tractpolygonlayer.on("load", function(evt) {
tractpolyFT.grid.set('sort', [{
attribute: "name"
}]);
var extent = tractpolygonlayer.fullExtent;
if (webMercatorUtils.canProject(extent, map)) {
map.on("extent-change", lang.hitch(this, function(params) {
// do not highlight the features when the map extent changes, as can be seen from below...it triggers a selection
tractpolygonlayer.setSelectionSymbol(null);
// taken from https://community.esri.com/thread/173929
var query = new Query();
query.geometry = params.extent;
query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
tractpolygonlayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
}))
}
});
//#endregion
}
// the function below shows/hides the appropriate feature table, based on the map scale
function showHideGridAndLegend() {
//console.log(map.getScale());
switch (true) {
case (map.getScale() >= 4622324):
domUtils.show(registry.byId('citypoints'));
domUtils.hide(registry.byId('statepolys'));
domUtils.hide(registry.byId('tractpolys'));
// the feature table is sometimes not shown expanded when the window showing it opens
// a search online led me to a post that recommended re-sizing the table, after the window has been opened
// this is an attempt that only works occasionally, right now
if (citypointFT) {
citypointFT.resize();
}
break;
case (map.getScale() < 4622324 && map.getScale() > 1155581):
domUtils.hide(registry.byId('citypoints'));
domUtils.show(registry.byId('statepolys'));
domUtils.hide(registry.byId('tractpolys'));
// the feature table is sometimes not shown expanded when the window showing it opens
// a search online led me to a post that recommended re-sizing the table, after the window has been opened
// this is an attempt that only works occasionally, right now
if (statepolyFT) {
statepolyFT.resize();
}
break;
case (map.getScale() <= 1155581):
domUtils.hide(registry.byId('citypoints'));
domUtils.hide(registry.byId('statepolys'));
domUtils.show(registry.byId('tractpolys'));
// the feature table is sometimes not shown expanded when the window showing it opens
// a search online led me to a post that recommended re-sizing the table, after the window has been opened
// this is an attempt that only works occasionally, right now
if (tractpolyFT) {
tractpolyFT.resize();
}
break;
default:
domUtils.hide(registry.byId('citypoints'));
domUtils.hide(registry.byId('statepolys'));
domUtils.hide(registry.byId('tractpolys'));
break;
}
}
// the function below zooms to the map extent of the results of a query
function getMapExtentOnZoom(result) {
// without the delays in calling the functions below, the functionality was not consistent.
if (result.features[0] !== 'undefined' && typeof result.features[0] !== 'undefined') {
setTimeout(function() {
//map.setExtent(result.features[0].geometry.getExtent().expand(1.45));
map.setExtent(result.features[0].geometry.getExtent(), true);
}, 450);
} else {
setTimeout(function() {
map.setExtent(initialExtent, true);
}, 450);
}
}
// function that calls individual functions to load the layers and tables and zoom, if necessary
function LoadLayers() {
renderedField = 'pop2000';
LoadCityPointLayer();
LoadStatePolygonLayer();
LoadTractPolygonLayer();
}
// remove layers from the map
function RemoveLayers() {
map.removeLayer(citypointlayer);
map.removeLayer(statepolygonlayer);
map.removeLayer(tractpolygonlayer);
}
// load the feature layers when the map loads
map.on("load", function() {
// add feature layers to the map and associated behaviors of feature layers
LoadLayers();
// set initil visibility of buttons/divs/etc.
setInitialVisibilityOfControls();
});
// determine which feature table to show when a user zooms
map.on("extent-change", showHideGridAndLegend);
});
</script>
</head>
<body class="claro esri">
<div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'" style="width:100%; height:100%;" id="allContent">
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center', splitter:true" style="height:50%">
<div id="map">
<div id="divShowHideTable">
<div id="divShownTable">
<img alttext="Image that displays when the Feature Table is showing." src="images/SelectRelatedRecords16.png" id="imgTable" tooltip="Show/Hide Table" />
</div>
</div>
</div>
</div>
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'bottom', splitter:true" style="height:50%" id="divGrid">
<div id="citypoints"></div>
<div id="statepolys"></div>
<div id="tractpolys"></div>
</div>
</div>
</body>
</html>
Hi, Robert. Thank you again VERY much for taking the time to investigate this issue. I am still seeing a similar issue, as before.
For example, when zoomed into the Counties, the table header shows the correct number of values. However, the table grid shows values not currently shown on the map.
As a matter of fact, even when viewing Cities and when zoomed into the MidWest, Hawaii is displayed in the table.
And again, when zooming back out from Cities, the table header count does not update correctly.
Is this normal behavior?
Thanks...Chris
Chris,
OK the way I was working around the FeatureTable filtering on extent does not work in all cases (when the OIDs and table rowIDs do not coincide). So you will have to use 3.18 of the API that fixes those issues:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Feature Table Example For ESRI</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.18/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.18/esri/css/esri.css">
<script src="https://js.arcgis.com/3.18/"></script>
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#map {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#citypoints,
#statepolys,
#countypolys {
background-color: white;
z-index: 50;
width: 100%;
height: 100%;
}
#divShowHideTable {
position: absolute;
top: 317px;
left: 20px;
z-index: 50;
}
#imgTable:hover {
cursor: pointer;
}
</style>
<script>
// declare variables and instantiate some
var map, grid, fl_url, symbol, polygonSymbol, highlightSymbol, pointSymbol, outlineSymbol, line, renderer, featureLayer, loading, myFeatureTable, idx, title, content, drawingOptions, placeholdertxt, whereclause, fieldsToDisplay,
selectionToolbar, val, fieldsoutputted, fieldsarray, lblgridheadertxt, citypointlayer, stateoutlinelayer, cityoutlinelayer, statepolygonlayer, countypolygonlayer, citypointrenderer, stateoutlinerender, cityoutlinerenderer,
statepolygonrenderer, countypolygonrenderer, tb, citypointFT, statepolyFT, countypolyFT, rfrshtbls, initld;
var visiblelayers = [],
symbolArray = [],
labelArray = [],
fieldsToSearch = [];
var renderedField = 'pop2000';
var DataUnavailableTxt = "Population < 50",
oldExtent = null;
// initialize modules and classes
require([
"esri/map", "esri/graphic", "esri/dijit/Basemap", "esri/dijit/BasemapLayer", "esri/dijit/BasemapGallery", "esri/arcgis/utils", "esri/urlUtils", "esri/geometry/webMercatorUtils", "esri/dijit/Search", "esri/layers/FeatureLayer",
"esri/dijit/FeatureTable", "esri/geometry/Extent", "esri/geometry/Polygon", "esri/symbols/SimpleFillSymbol", "esri/layers/ArcGISDynamicMapServiceLayer", "esri/layers/ImageParameters", "esri/InfoTemplate",
"esri/renderers/ClassBreaksRenderer", "esri/tasks/GenerateRendererParameters", "esri/tasks/GenerateRendererTask", "esri/tasks/ClassBreaksDefinition", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
"esri/renderers/SimpleRenderer", "esri/tasks/AlgorithmicColorRamp", "esri/lang", "dojo/_base/lang", "esri/toolbars/draw", "esri/geometry/Point", "esri/geometry/geometryEngine", "esri/dijit/Scalebar", "esri/SpatialReference",
"esri/layers/LayerDrawingOptions", "esri/request", "dojo/dom-construct", "esri/tasks/QueryTask", "esri/tasks/query", "esri/Color", "dijit/form/Slider", "dojo/dom-style", "dgrid/Selection", "dojo/on", "esri/domUtils",
"dojo/_base/array", "dojox/gfx", "esri/symbols/jsonUtils", "dojo/dom", "dijit/form/Button", "dojo/data/ItemFileReadStore", "dijit/registry", "dojo/parser", "dojo/_base/declare", "dijit/layout/BorderContainer",
"dijit/layout/ContentPane", "dijit/form/TextBox", "dgrid/extensions/ColumnHider", "dojo/domReady!"
], function(
Map, Graphic, Basemap, BasemapLayer, BasemapGallery, arcgisUtils, urlUtils, webMercatorUtils, Search, FeatureLayer,
FeatureTable, Extent, Polygon, SimpleFillSymbol, ArcGISDynamicMapServiceLayer, ImageParameters, InfoTemplate,
ClassBreaksRenderer, GenerateRendererParameters, GenerateRendererTask, ClassBreaksDefinition, SimpleMarkerSymbol, SimpleLineSymbol,
SimpleRenderer, AlgorithmicColorRamp, esriLang, lang, Draw, Point, geometryEngine, Scalebar, SpatialReference,
LayerDrawingOptions, esriRequest, domConstruct, QueryTask, Query, Color, Slider, domStyle, Selection, on, domUtils,
arrayUtils, gfx, jsonUtils, dom, Button, ItemFileReadStore, registry, parser, declare, BorderContainer,
ContentPane, TextBox, ColumnHider
) {
parser.parse();
var DynamicMapServiceURL = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer";
// define symbols
highlightSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 3)).setColor(new Color([125, 125, 125, 0.35]));
polygonSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
pointSymbol = new SimpleMarkerSymbol().setStyle(SimpleMarkerSymbol.STYLE_CIRCLE).setSize(8).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
outlineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 1);
// intial map extent
var initialExtent = new esri.geometry.Extent({
"xmin": -19525916.67711644,
"ymin": 1491562.5722065126,
"xmax": -2404022.3412415087,
"ymax": 9318714.26860648,
"spatialReference": {
"wkid": 102100
}
});
// instantiate infoTemplate
var infotemp = new InfoTemplate();
// define the dynamic map service layer and the image parameter attribute it uses
var imageParameters = new ImageParameters();
imageParameters.format = "png";
var dynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(DynamicMapServiceURL, {
"opacity": 1.0,
"imageParameters": imageParameters
});
// add a map to the page
map = new Map("map", {
basemap: "gray",
extent: initialExtent
});
// events that fire, based on actions in the UI
// the function below displays an error message and hides the div in which the map is drawn
function showErr(err) {
console.log("Error Details: ", err);
}
on(dom.byId("imgTable"), "click", function(e) {
toggle_visibility();
});
function toggle_visibility() {
var appLayout = registry.byId("allContent");
var bottPanel = registry.byId("divGrid");
domUtils.toggle(bottPanel);
appLayout.resize();
}
// set the initial visibility of the controls in the UI
function setInitialVisibilityOfControls() {
domUtils.show(dom.byId('divHiddenTable'));
var appLayout = registry.byId("allContent");
var bottPanel = registry.byId("divGrid");
domUtils.hide(bottPanel);
appLayout.resize();
}
//create new FeatureTable and set its properties
function AddGrid(lyrid, gridloc) {
var existingGrid = registry.byId(gridloc);
if (existingGrid) {
existingGrid.destroyRecursive(true);
}
switch(lyrid){
case 0: {
citypointFT = new FeatureTable({
"featureLayer": citypointlayer,
"map": map,
"showStatistics": false,
"zoomToSelection": false,
"syncSelection": true,
"outFields": ["*"]
}, gridloc);
citypointFT.startup();
citypointFT.sort("areaname", false);
break;
}
case 2: {
statepolyFT = new FeatureTable({
"featureLayer": statepolygonlayer,
"map": map,
"showStatistics": false,
"zoomToSelection": false,
"syncSelection": true,
"outFields": ["*"]
}, gridloc);
statepolyFT.startup();
statepolyFT.sort("state_name", false);
break;
}
case 3: {
countypolyFT = new FeatureTable({
"featureLayer": countypolygonlayer,
"map": map,
"showStatistics": false,
"zoomToSelection": false,
"syncSelection": true,
"outFields": ["*"]
}, gridloc);
countypolyFT.startup();
countypolyFT.sort("areaname", false);
break;
}
}
}
// the functions below dynamically generate a renderer and apply that
// renderer generated by the createRenderer function above to the featureLayer and adds labels.
// using individual functions, as trying to use a generic/parameterized one before did not work
function applyctyptRenderer(citypointrenderer) {
citypointrenderer.defaultLabel = DataUnavailableTxt;
citypointrenderer.defaultSymbol = pointSymbol;
citypointlayer.setRenderer(citypointrenderer);
citypointlayer.renderer.setOpacityInfo(0.7);
map.addLayer(citypointlayer);
}
function applyctypolyRenderer(statepolygonrenderer) {
statepolygonrenderer.defaultLabel = DataUnavailableTxt;
statepolygonrenderer.defaultSymbol = polygonSymbol;
statepolygonlayer.setRenderer(statepolygonrenderer);
statepolygonlayer.renderer.setOpacityInfo(0.7);
map.addLayer(statepolygonlayer);
}
function applytrtpolyRenderer(countypolygonrenderer) {
countypolygonrenderer.defaultLabel = DataUnavailableTxt;
countypolygonrenderer.defaultSymbol = polygonSymbol;
countypolygonlayer.setRenderer(countypolygonrenderer);
countypolygonlayer.renderer.setOpacityInfo(0.7);
map.addLayer(countypolygonlayer);
}
function createRenderer(lyr, field) {
var classDef = new ClassBreaksDefinition();
classDef.classificationField = field;
classDef.classificationMethod = "natural-breaks";
classDef.breakCount = 7;
switch (lyr) {
case 0:
classDef.baseSymbol = pointSymbol;
break;
case 2:
classDef.baseSymbol = polygonSymbol;
break;
case 3:
classDef.baseSymbol = polygonSymbol;
break;
default:
classDef.baseSymbol = outlineSymbol;
break;
}
var colorRamp = new AlgorithmicColorRamp();
colorRamp.fromColor = new Color.fromHex("#ffffd9");
colorRamp.toColor = new Color.fromHex("#081d58");
colorRamp.algorithm = "hsv";
classDef.colorRamp = colorRamp;
var params = new GenerateRendererParameters();
params.classificationDefinition = classDef;
params.where = whereclause;
var generateRenderer = new GenerateRendererTask(DynamicMapServiceURL + "/" + lyr);
// apply a different renderer, based on the layer
switch (lyr) {
case 0:
generateRenderer.execute(params, applyctyptRenderer, showErr);
break;
case 2:
generateRenderer.execute(params, applyctypolyRenderer, showErr);
break;
case 3:
generateRenderer.execute(params, applytrtpolyRenderer, showErr);
break;
default:
break;
}
}
function LoadCityPointLayer() {
//#region CityPointLayer
// add city point layer
citypointlayer = new FeatureLayer(DynamicMapServiceURL + "/0", {
mode: FeatureLayer.MODE_ONDEMAND,
outFields: ["*"],
id: "City Point Layer",
minScale: 0,
maxScale: 4622324
});
AddGrid(0, "citypoints");
createRenderer(0, renderedField);
//#endregion
}
function LoadStatePolygonLayer() {
//#region StatePolygonLayer
// add state polygon layer
statepolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/2", {
mode: FeatureLayer.MODE_ONDEMAND,
outFields: ["*"],
id: "State Polygon Layer",
minScale: 4622324,
maxScale: 1155581
});
createRenderer(2, renderedField);
AddGrid(2, "statepolys");
//#endregion
}
function Loadcountypolygonlayer() {
//#region countypolygonlayer
// add county polygon layer
countypolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/3", {
mode: FeatureLayer.MODE_ONDEMAND,
outFields: ["*"],
id: "County Polygon Layer",
minScale: 1155581,
maxScale: 0
});
createRenderer(3, renderedField);
AddGrid(3, "countypolys");
//#endregion
}
// the function below shows/hides the appropriate feature table, based on the map scale
function showHideGridAndLegend(params) {
var query = new Query();
if(countypolygonlayer && countypolygonlayer.visibleAtMapScale){
domUtils.hide(registry.byId('citypoints'));
domUtils.hide(registry.byId('statepolys'));
domUtils.show(registry.byId('countypolys'));
query.geometry = webMercatorUtils.project(params.extent, new SpatialReference({wkid:4326}));
query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
countypolygonlayer.queryIds(query, lang.hitch(this, function(objectIds) {
countypolyFT.filterRecordsByIds(objectIds);
//countypolyFT._showSelectedRecords();
//countypolyFT._gridTitleNode.innerHTML = countypolygonlayer.name + ' (' + (objectIds.length != 'undefined' ? (objectIds.length > 1 ? objectIds.length + ' Features)' : 1 + ' Feature)') : "");
countypolyFT.resize();
}));
}else if(statepolygonlayer && statepolygonlayer.visibleAtMapScale){
domUtils.hide(registry.byId('citypoints'));
domUtils.show(registry.byId('statepolys'));
domUtils.hide(registry.byId('countypolys'));
query.geometry = webMercatorUtils.project(params.extent, new SpatialReference({wkid:4326}));
query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
statepolygonlayer.queryIds(query, lang.hitch(this, function(objectIds) {
statepolyFT.filterRecordsByIds(objectIds);
//statepolyFT._showSelectedRecords();
//statepolyFT._gridTitleNode.innerHTML = statepolygonlayer.name + ' (' + (objectIds.length != 'undefined' ? (objectIds.length > 1 ? objectIds.length + ' Features)' : 1 + ' Feature)') : "");
statepolyFT.resize();
}));
}else if(citypointlayer && citypointlayer.visibleAtMapScale){
domUtils.show(registry.byId('citypoints'));
domUtils.hide(registry.byId('statepolys'));
domUtils.hide(registry.byId('countypolys'));
query.geometry = webMercatorUtils.project(params.extent, new SpatialReference({wkid:4326}));
query.spatialRelationship = Query.SPATIAL_REL_CONTAINS;
citypointlayer.queryIds(query, lang.hitch(this, function(objectIds) {
citypointFT.filterRecordsByIds(objectIds);
//citypointFT._showSelectedRecords();
//citypointFT._gridTitleNode.innerHTML = citypointlayer.name + ' (' + (objectIds.length != 'undefined' ? (objectIds.length > 1 ? objectIds.length + ' Features)' : 1 + ' Feature)') : "");
citypointFT.resize();
citypointFT.refresh();
}));
}
}
// function that calls individual functions to load the layers and tables and zoom, if necessary
function LoadLayers() {
renderedField = 'pop2000';
LoadCityPointLayer();
LoadStatePolygonLayer();
Loadcountypolygonlayer();
}
// load the feature layers when the map loads
map.on("load", function() {
// add feature layers to the map and associated behaviors of feature layers
LoadLayers();
// set initil visibility of buttons/divs/etc.
setInitialVisibilityOfControls();
});
// determine which feature table to show when a user zooms
map.on("extent-change", showHideGridAndLegend);
});
</script>
</head>
<body class="claro esri">
<div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'" style="width:100%; height:100%;" id="allContent">
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center', splitter:true" style="height:50%">
<div id="map">
<div id="divShowHideTable">
<div id="divShownTable">
<img alttext="Image that displays when the Feature Table is showing." src="images/SelectRelatedRecords16.png" id="imgTable" tooltip="Show/Hide Table" />
</div>
</div>
</div>
</div>
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'bottom', splitter:true" style="height:50%" id="divGrid">
<div id="citypoints"></div>
<div id="statepolys"></div>
<div id="countypolys"></div>
</div>
</div>
</body>
</html>
Thanks, Robert. I will give this a try.
- Chris
Thanks again, Robert! It looks like your solution will work for us. We are integrating this into a custom BI tool, so the code was modified a bit. Thanks again!
- Chris