AnsweredAssumed Answered

Custom widget: combine attribute inspector & live video feed into one widget

Question asked by L.Stroupe on Jun 29, 2018
Latest reply on Jul 10, 2018 by L.Stroupe



I am trying to create a custom widget that combines the attribute inspector in one tab, and a live video feed in another tab. I'm currently stuck on populating the contents of each tab. I'm trying to accomplish this via functions, but my results keep showing up as 'undefined' when i run it in the sandbox: ArcGIS API for JavaScript Sandbox  



Any help would be greatly appreciated!!

Thank you 



<!DOCTYPE html>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">

<link rel="stylesheet" href="">
#mapDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;

body {
background-color: #FFF;
overflow: hidden;
font-family: "Trebuchet MS";

<script src=""></script>




function (
Map, InfoTemplate, FeatureLayer, Query, AttributeInspector, InfoWindow,
dom, domConstruct, number, on, parser,
TabContainer, BorderContainer, ContentPane, Button
) {

//create the infoWindow
var infoWindow = new InfoWindow({}, domConstruct.create("div"));

//create the map
var map = new Map("mapDiv", {
basemap: "topo",
center: [-96.755, 33.176],
zoom: 18,
infoWindow: infoWindow

//set the infoTemplate for the new infoWindow
var infoTemplate = new InfoTemplate();

//define the camera layer that will be added to map
var cameras = new FeatureLayer("myURL", {
mode: FeatureLayer.MODE_SNAPSHOT,
infoTemplate: infoTemplate,
outFields: ["*"]

//add the camera layer to the map

//resize the infoWindow
map.infoWindow.resize(300, 300);

//function that formats and populates the infoWindow content's 2 tabs
function getWindowContent(graphic) {
//make a container for tabs
var tc = new dijit.layout.TabContainer({
style: "height: 100%; width: 100%;"
}, dojo.create("div"));

//tab 1
var cp1 = new dijit.layout.ContentPane({
title: "Video"

//tab 2
var cp2 = new dijit.layout.ContentPane({
title: "Edit"

return tc.domNode;

//function that gets the camera url to open and display in tab1
function getVideo(evt) {
selectedCamera = evt.feature.attributes.URL;
return selectedCamera;

//function that creates the attribute inspector tab2
function initSelectToolbar(evt) {
var selectQuery = new Query();

map.on("click", function (evt) {
selectQuery.geometry = evt.mapPoint;
selectQuery.distance = 4;
selectQuery.units = "feet"
selectQuery.returnGeometry = true;
cameras.selectFeatures(selectQuery, FeatureLayer.SELECTION_NEW, function (features) {
if (features.length > 0) {
//store the current feature
updateFeature = features[0];
map.infoWindow.setTitle(features[0].getLayer().name);, map.getInfoWindowAnchor(evt.screenPoint));
else {

map.infoWindow.on("hide", function () {

var layerInfos = [
'featureLayer': cameras,
'showAttachments': false,
'isEditable': true,
'fieldInfos': [
{ 'fieldName': 'CAMERA_NAME', 'label': 'Name', 'isEditable': false },
{ 'fieldName': 'VideoStream', 'label': 'Video Stream?', 'isEditable': true },
{ 'fieldName': 'CorrectView', 'label': 'Correct View?', 'isEditable': true },
{ 'fieldName': 'Comments', 'label': 'Comments', 'isEditable': true }
//Initialize Attribute Inspector
var attInspector = new AttributeInspector({
layerInfos: layerInfos
}, domConstruct.create("div"));

//add a save button next to the delete button
var saveButton = new Button({ label: "Save", "class": "saveButton" }, domConstruct.create("div"));, attInspector.deleteBtn.domNode, "after");

saveButton.on("click", function () {
updateFeature.getLayer().applyEdits(null, [updateFeature], null);

//adds a close button next to the save button
var closeButton = new Button({ label: "Close", "class": "closeButton" }, domConstruct.create("div"));, saveButton.domNode, "after");

//by clicking the close button the following action will happen
closeButton.on("click", function () {

attInspector.on("attribute-change", function (evt) {
//store the updates to apply when the save button is clicked
updateFeature.attributes[evt.fieldName] = evt.fieldValue;

attInspector.on("next", function (evt) {
updateFeature = evt.feature;
console.log("Next " + updateFeature.attributes.OBJECTID);

attInspector.on("delete", function (evt) {
evt.feature.getLayer().applyEdits(null, null, [evt.feature]);



<body class="soria">
<div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline', gutters:true" style="width: 100%; height: 100%; margin: 0;">
<div id="mapDiv" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'"></div>