Skip to content

Instantly share code, notes, and snippets.

@kflaw
Last active August 29, 2015 14:08
Show Gist options
  • Save kflaw/ba632838f52c900f321d to your computer and use it in GitHub Desktop.
Save kflaw/ba632838f52c900f321d to your computer and use it in GitHub Desktop.
cmv identify dijit
define([
'dojo/_base/declare',
'dijit/_WidgetBase',
'dijit/_TemplatedMixin',
'dijit/_WidgetsInTemplateMixin',
'dijit/MenuItem',
'dojo/_base/lang',
'dojo/_base/array',
'dojo/promise/all',
'dojo/topic',
'dojo/on',
'dojo/dom-construct',
'dojo/query',
'esri/layers/ImageServiceParameters',
'esri/layers/MosaicRule',
'esri/layers/ArcGISImageServiceLayer',
'dojo/store/Memory',
'esri/tasks/IdentifyTask',
'esri/tasks/IdentifyParameters',
'esri/dijit/PopupTemplate',
'dojo/text!./Identify/templates/Identify.html',
'dijit/form/Form',
'dijit/form/FilteringSelect',
'xstyle/css!./Identify/css/Identify.css',
'dojo/dom-attr',
'dijit/form/HorizontalSlider',
'dijit/TooltipDialog',
'dijit/popup',
'dojo/dom',
'dojo/dom-style',
'dijit/form/HorizontalRuleLabels',
'dojo/domReady!'
], function (declare, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, MenuItem, lang, array, all, topic, on, domConstruct, query,
ImageServiceParameters, MosaicRule, ArcGISImageServiceLayer, Memory, IdentifyTask, IdentifyParameters, PopupTemplate, IdentifyTemplate,
domAttr, HorizontalSlider, TooltipDialog, popup, dom, domStyle, HorizontalRuleLabels) {
var imageServiceLayer = null;
var imageInt = 0;
var feature;
var popupContent;
var imageID;
var popContent2;
var removeLayer;
var myDialog;
var imageSlider;
return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
widgetsInTemplate: true,
templateString: IdentifyTemplate,
baseClass: 'gis_IdentifyDijit',
mapClickMode: null,
identifies: {},
infoTemplates: {},
ignoreOtherGraphics: true,
createDefaultInfoTemplates: true,
layerSeparator: '||',
allLayersId: '***',
postCreate: function () {
this.inherited(arguments);
if (!this.identifies) {
this.identifies = {};
}
this.layers = [];
array.forEach(this.layerInfos, function (layerInfo) {
var lyrId = layerInfo.layer.id;
var layer = this.map.getLayer(lyrId);
if (layer) {
var url = layer.url;
// handle feature layers
if (layer.declaredClass === 'esri.layers.FeatureLayer') {
// If is a feature layer that does not support
// Identify (Feature Service), create an
// infoTemplate for the graphic features. Create
// it only if one does not already exist.
if (layer.capabilities && layer.capabilities.toLowerCase().indexOf('data') < 0) {
if (!layer.infoTemplate) {
var infoTemplate = this.getInfoTemplate(layer);
if (infoTemplate) {
layer.setInfoTemplate(infoTemplate);
return;
}
}
}
// If it is a feature Layer, we get the base url
// for the map service by removing the layerId.
var lastSL = url.lastIndexOf('/' + layer.layerId);
if (lastSL > 0) {
url = url.substring(0, lastSL);
}
}
this.layers.push({
ref: layer,
layerInfo: layerInfo,
identifyTask: new IdentifyTask(url)
});
// rebuild the layer selection list when any layer is hidden
// but only if we have a UI
if (this.parentWidget) {
layer.on('visibility-change', lang.hitch(this, function (evt) {
if (evt.visible === false) {
this.createIdentifyLayerList();
}
}));
}
}
}, this);
this.own(topic.subscribe('mapClickMode/currentSet', lang.hitch(this, 'setMapClickMode')));
this.map.on('click', lang.hitch(this, function (evt) {
if (this.mapClickMode === 'identify') {
this.executeIdentifyTask(evt);
}
}));
if (this.mapRightClickMenu) {
this.addRightClickMenu();
}
// rebuild the layer selection list when the map is updated
// but only if we have a UI
if (this.parentWidget) {
this.createIdentifyLayerList();
this.map.on('update-end', lang.hitch(this, function () {
this.createIdentifyLayerList();
}));
}
addLink = domConstruct.create("a",{
"class": "action",
"id": "rasterLock",
"innerHTML": "Add image",
"href": "javascript:void(0);"
}, query(".actionList", this.map.infoWindow.domNode)[0]);
on(addLink, 'click', lang.hitch(this, function(event) {
//dojo.setAttr(dojo.byId("rasterLock"), "innerHTML", "Adding image...");
feature = this.map.infoWindow.getSelectedFeature();
popupContent = parseInt(feature.attributes.is_oid);
if (isNaN(popupContent)) {
alert('Cannot add image for selected feature.');
}
else {
imageInt = imageInt + 1;
imageID = "Image" + popupContent;
var arr = [popupContent];
var imgParams = new ImageServiceParameters();
imgParams.noData = 0;
var mr = new MosaicRule();
mr.method = MosaicRule.METHOD_LOCKRASTER;
mr.lockRasterIds = arr;
imgParams.mosaicRule = mr;
var MC_ImageService = "http://sv04esri:6080/arcgis/rest/services/Testing/IS_test/ImageServer";
imageServiceLayer = new ArcGISImageServiceLayer(MC_ImageService, {
id: imageID,
imageServiceParameters: imgParams,
opacity: 0.75
});
dojo.setAttr(dojo.byId("rasterLock"), "innerHTML", "Add image");
this.map.addLayer(imageServiceLayer);
}
})
);
removeLink = domConstruct.create("a",{
"class": "action",
"id": "rasterRemove",
"innerHTML": "Remove image",
"href": "javascript:void(0);"
}, query(".actionList", this.map.infoWindow.domNode)[0]);
on(rasterRemove, 'click', lang.hitch(this, function() {
feature2 = this.map.infoWindow.getSelectedFeature();
popContent2 = parseInt(feature2.attributes.is_oid);
removeLayer = "Image" + popContent2;
if (isNaN(popContent2)) {
alert('There is no image associated with this feature to remove.');
}
// if (imageInt == 0){
// alert("There are currently no images loaded in the map.");
// }
else if (removeLayer !== "ImageNaN") {
var imageLayer = this.map.getLayer(removeLayer);
if (typeof imageLayer !== 'undefined') {
this.map.removeLayer(imageLayer);
imageInt = imageInt - 1
}
else {
alert("This image is not loaded in the map.");
}
}
})
);
transparencyLink = domConstruct.create("a",{
"class": "action",
"id": "adjustTransparency",
"innerHTML": " Image opacity",
"href": "javascript:void(0);"
}, query(".actionList", this.map.infoWindow.domNode)[0]);
imageSlider = new HorizontalSlider({
value: 7.5,
minimum: 0,
maximum: 10,
intermediateChanges: true,
discreteValues: 11,
showButtons: false,
style: "width:200px;",
onChange: lang.hitch(this, function(value) {
transparencyLayer.setOpacity(value / 10);
domStyle.set(transparencyLayer, 'opacity', value);
})
}, "imageSlider");
// var rule = new HorizontalRuleLabels({
// labels: ['100%', '50%', '0%'],
// style: 'height:1em;font-size:75%;'
// }, imageSlider.bottomDecoration);
// rule.startup();
imageSlider.startup();
var myTooltipDialog = new dijit.TooltipDialog({
id: 'myTooltipDialog',
style: "width: 225px;",
content: imageSlider,
onMouseLeave: function(){
dijit.popup.close(myTooltipDialog);
}
});
on(transparencyLink, 'click', lang.hitch(this, function() {
dijit.popup.open({
popup: myTooltipDialog,
around: transparencyLink
});
})
);
},
addRightClickMenu: function () {
this.map.on('MouseDown', lang.hitch(this, function (evt) {
this.mapRightClick = evt;
}));
this.mapRightClickMenu.addChild(new MenuItem({
label: 'Identify here',
onClick: lang.hitch(this, 'handleRightClick')
}));
},
executeIdentifyTask: function (evt) {
if (!this.checkForGraphicInfoTemplate(evt)) {
return;
}
this.map.infoWindow.hide();
this.map.infoWindow.clearFeatures();
var mapPoint = evt.mapPoint;
var identifyParams = this.createIdentifyParams(mapPoint);
var identifies = [];
var identifiedlayers = [];
var selectedLayer = this.getSelectedLayer();
array.forEach(this.layers, lang.hitch(this, function (layer) {
var layerIds = this.getLayerIds(layer, selectedLayer);
if (layerIds.length > 0) {
var params = lang.clone(identifyParams);
params.layerIds = layerIds;
identifies.push(layer.identifyTask.execute(params));
identifiedlayers.push(layer);
}
}));
if (identifies.length > 0) {
this.map.infoWindow.setTitle('Identifying...');
this.map.infoWindow.setContent('<div class="loading"></div>');
this.map.infoWindow.show(mapPoint);
all(identifies).then(lang.hitch(this, 'identifyCallback', identifiedlayers), lang.hitch(this, 'identifyError'));
}
},
checkForGraphicInfoTemplate: function (evt) {
if (evt.graphic) {
// handle feature layers that come from a feature service
// and may already have an info template
var layer = evt.graphic._layer;
if (layer.infoTemplate || (layer.capabilities && layer.capabilities.toLowerCase().indexOf('data') < 0)) {
return false;
}
if (!this.ignoreOtherGraphics) {
// handles graphic from another type of graphics layer
// added to the map and so the identify is not found
if (!this.identifies.hasOwnProperty(layer.id)) {
return false;
}
// no layerId (graphics) or sublayer not defined
if (isNaN(layer.layerId) || !this.identifies[layer.id].hasOwnProperty(layer.layerId)) {
return false;
}
}
}
return true;
},
createIdentifyParams: function (point) {
var identifyParams = new IdentifyParameters();
identifyParams.tolerance = this.identifyTolerance;
identifyParams.returnGeometry = true;
identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_VISIBLE;
identifyParams.geometry = point;
identifyParams.mapExtent = this.map.extent;
identifyParams.width = this.map.width;
identifyParams.height = this.map.height;
identifyParams.spatialReference = this.map.spatialReference;
return identifyParams;
},
getSelectedLayer: function () {
var selectedLayer = this.allLayersId; // default is all layers
// if we have a UI, then get the selected layer
if (this.parentWidget) {
var form = this.identifyFormDijit.get('value');
if (!form.identifyLayer || form.identifyLayer === '') {
this.identifyLayerDijit.set('value', selectedLayer);
} else {
selectedLayer = form.identifyLayer;
}
}
return selectedLayer;
},
getLayerIds: function (layer, selectedLayer) {
var arrIds = selectedLayer.split(this.layerSeparator);
var allLayersId = this.allLayersId;
var ref = layer.ref,
selectedIds = layer.layerInfo.layerIds;
var layerIds = [];
if (ref.visible) {
if (arrIds[0] === allLayersId || ref.id === arrIds[0]) {
if (arrIds.length > 1 && arrIds[1]) { // layer explicity requested
layerIds = [arrIds[1]];
} else if ((ref.declaredClass === 'esri.layers.FeatureLayer') && !isNaN(ref.layerId)) { // feature layer
// do not allow feature layer that does not support
// Identify (Feature Service)
if (ref.capabilities && ref.capabilities.toLowerCase().indexOf('data') > 0) {
layerIds = [ref.layerId];
}
} else if (ref.layerInfos) {
layerIds = this.getLayerInfos(ref, selectedIds);
}
}
}
return layerIds;
},
getLayerInfos: function (ref, selectedIds) {
var layerIds = [];
array.forEach(ref.layerInfos, lang.hitch(this, function (layerInfo) {
if (!this.includeSubLayer(layerInfo, ref, selectedIds)) {
return;
}
layerIds.push(layerInfo.id);
}));
return layerIds;
},
identifyCallback: function (identifiedlayers, responseArray) {
var fSet = [];
array.forEach(responseArray, function (response, i) {
var ref = identifiedlayers[i].ref;
array.forEach(response, function (result) {
result.feature.geometry.spatialReference = this.map.spatialReference; //temp workaround for ags identify bug. remove when fixed.
if (result.feature.infoTemplate === undefined) {
var infoTemplate = this.getInfoTemplate(ref, null, result);
if (infoTemplate) {
result.feature.setInfoTemplate(infoTemplate);
} else {
return;
}
}
fSet.push(result.feature);
}, this);
}, this);
this.map.infoWindow.setFeatures(fSet);
},
identifyError: function (err) {
this.map.infoWindow.hide();
topic.publish('viewer/handleError', {
source: 'Identify',
error: err
});
},
handleRightClick: function () {
this.executeIdentifyTask(this.mapRightClick);
},
getInfoTemplate: function (layer, layerId, result) {
var popup = null;
if (result) {
layerId = result.layerId;
} else if (layerId === null) {
layerId = layer.layerId;
}
// see if we have a Popup config defined for this layer
if (this.identifies.hasOwnProperty(layer.id)) {
if (this.identifies[layer.id].hasOwnProperty(layerId)) {
popup = this.identifies[layer.id][layerId];
if (popup) {
if (typeof (popup.declaredClass) !== 'string') { // has it been created already?
popup = new PopupTemplate(popup);
this.identifies[layer.id][layerId] = popup;
}
}
}
}
// if no Popup config found, create one with all attributes or layer fields
if (!popup) {
popup = this.createInfoTemplate(layer, layerId, result);
}
return popup;
},
createInfoTemplate: function (layer, layerId, result) {
var popup = null, fieldInfos = [];
var layerName = this.getLayerName(layer);
if (result) {
layerName = result.layerName;
}
// from the results
if (result && result.feature) {
var attributes = result.feature.attributes;
if (attributes) {
for (var prop in attributes) {
if (attributes.hasOwnProperty(prop)) {
fieldInfos.push({
fieldName: prop,
visible: true
});
}
}
}
// from the outFields of the layer
} else if (layer._outFields && (layer._outFields.length) && (layer._outFields[0] !== '*')) {
var fields = layer.fields;
array.forEach(layer._outFields, function (fieldName) {
var foundField = array.filter(fields, function (field) {
return (field.name === fieldName);
});
if (foundField.length > 0) {
fieldInfos.push({
fieldName: foundField[0].name,
label: foundField[0].alias,
visible: true
});
}
});
// from the fields layer
} else if (layer.fields) {
array.forEach(layer.fields, function (field) {
fieldInfos.push({
fieldName: field.name,
label: field.alias,
visible: true
});
});
}
if (fieldInfos.length > 0) {
popup = new PopupTemplate({
title: layerName,
fieldInfos: fieldInfos,
showAttachments: (layer.hasAttachments)
});
if (!this.identifies[layer.id]) {
this.identifies[layer.id] = {};
}
this.identifies[layer.id][layerId] = popup;
}
return popup;
},
createIdentifyLayerList: function () {
var id = null;
var identifyItems = [];
var selectedId = this.identifyLayerDijit.get('value');
var sep = this.layerSeparator;
array.forEach(this.layers, lang.hitch(this, function (layer) {
var ref = layer.ref,
selectedIds = layer.layerInfo.layerIds;
// only include layers that are currently visible
if (ref.visible) {
var name = this.getLayerName(layer);
if ((ref.declaredClass === 'esri.layers.FeatureLayer') && !isNaN(ref.layerId)) { // feature layer
identifyItems.push({
name: name,
id: ref.id + sep + ref.layerId
});
// previously selected layer is still visible so keep it selected
if (ref.id + sep + ref.layerId === selectedId) {
id = selectedId;
}
} else { // dynamic layer
array.forEach(ref.layerInfos, lang.hitch(this, function (layerInfo) {
if (!this.includeSubLayer(layerInfo, ref, selectedIds)) {
return;
}
identifyItems.push({
name: name + ' \\ ' + layerInfo.name,
id: ref.id + sep + layerInfo.id
});
// previously selected sublayer is still visible so keep it selected
if (ref.id + sep + layerInfo.id === selectedId) {
id = selectedId;
}
}));
}
}
}));
identifyItems.sort(function (a, b) {
return (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0);
});
this.identifyLayerDijit.set('disabled', (identifyItems.length < 1));
if (identifyItems.length > 0) {
identifyItems.unshift({
name: '*** All Visible Layers ***',
id: '***'
});
if (!id) {
id = identifyItems[0].id;
}
}
var identify = new Memory({
data: identifyItems
});
this.identifyLayerDijit.set('store', identify);
this.identifyLayerDijit.set('value', id);
},
includeSubLayer: function (layerInfo, ref, selectedIds) {
// exclude group layers
if (layerInfo.subLayerIds !== null) {
return false;
}
// only include sublayers that are currently visible
if (array.indexOf(ref.visibleLayers, layerInfo.id) < 0) {
return false;
}
// only include sublayers that are within the current map scale
if (!this.layerVisibleAtCurrentScale(layerInfo)) {
return false;
}
// restrict which layers are included
if (selectedIds) {
if (array.indexOf(selectedIds, layerInfo.id) < 0) {
return false;
}
}
// don't allow the layer if we don't have an infoTemplate
// already and creating a default one is not desired
if (!this.createDefaultInfoTemplates) {
var infoTemplate = this.getInfoTemplate(ref, layerInfo.id);
if (!infoTemplate) {
return false;
}
}
// all tests pass so include this sublayer
return true;
},
getLayerName: function (layer) {
var name = null;
if (layer.layerInfo) {
name = layer.layerInfo.title;
}
if (!name) {
array.forEach(this.layers, function (lyr) {
if (lyr.ref.id === layer.id) {
name = lyr.layerInfo.title;
return;
}
});
}
if (!name) {
name = layer.name;
if (!name && layer.ref) {
name = layer.ref._titleForLegend; // fall back to old method using title from legend
}
}
return name;
},
layerVisibleAtCurrentScale: function (layer) {
var mapScale = this.map.getScale();
return !(((layer.maxScale !== 0 && mapScale < layer.maxScale) || (layer.minScale !== 0 && mapScale > layer.minScale)));
},
setMapClickMode: function (mode) {
this.mapClickMode = mode;
var map = this.map;
array.forEach(map.graphicsLayerIds, function (layerID) {
var layer = map.getLayer(layerID);
if (layer) {
// add back any infoTemplates that
// had been previously removed
if (mode === 'identify') {
if (this.infoTemplates[layer.id]) {
layer.infoTemplate = lang.clone(this.infoTemplates[layer.id]);
}
// remove any infoTemplates that might
// interfere with clicking on a feature
} else {
if (layer.infoTemplate) {
this.infoTemplates[layer.id] = lang.clone(layer.infoTemplate);
layer.infoTemplate = null;
}
}
}
}, this);
}
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment