Skip to content

Instantly share code, notes, and snippets.

@raykendo
Created February 10, 2017 17:01
Show Gist options
  • Save raykendo/e3d0e9996afd25fd1f8bcd80d3947c71 to your computer and use it in GitHub Desktop.
Save raykendo/e3d0e9996afd25fd1f8bcd80d3947c71 to your computer and use it in GitHub Desktop.
Cleaning Export Web Map request plugin
/**
* Some people just need a paper map. ArcGIS Server provides a service to turn a web map into an image, pdf, or other file
* The process to generate these documents can be long and intensive (in relative web terms), taking up to 2 minutes to generate
* a document.
*/
/* globals: define*/
define([
"dojo/_base/lang",
"dojo/_base/array",
"dojo/json",
"esri/request"
], function (
lang, arrayUtils, JSON,
esriRequest
) {
/**
* Cleans irrelevant feature data from featureCollection layers
* @function cleanFeatureCollectionLayer
* @param {object} layer - layer data to clean
* @param {object} layer.layerDefinition - layer definition JSON
* @param {object} layer.featureSet - featureset containing relevant data
* @returns {object} - layer data with attributes not required for rendering removed.
*/
function cleanFeatureCollectionLayer(layer) {
var passTheseAttributes = [],
renderer = layer.layerDefinition.drawingInfo.renderer,
featureCleaner, cleanFeatures;
switch (renderer.type) {
case "simple":
// if simple, no attributes required for rendering
passTheseAttributes = [];
break;
case "unique":
// if unique, only unique fields need to be passed through
if (renderer.field1) {
passTheseAttributes.push(renderer.field1);
}
if (renderer.field2) {
passTheseAttributes.push(renderer.field2);
}
if (renderer.field3) {
passTheseAttributes.push(renderer.field3);
}
break;
case "classBreaks":
// class break renderer requires a field, and possibly a normalization field for rendering class breaks.
passTheseAttributes.push(renderer.field);
if (renderer.normalizationField) {
passTheseAttributes.push(renderer.normalizationField);
}
break;
}
/**
* recreates feature JSON with but filters out fields not necessary for rendering
* @function featureCleaner
* @param {object} feature
* @param {object} feature.geometry - shape of the feature
* @param {object} feature.attributes - name/value collection of data connected with the feature
* @param {object} [feature.symbol] - feature symbol JSON, denoting color, size, etc.
*/
featureCleaner = function (feature) {
var newFeature = {
geometry: feature.geometry,
attributes: {}
}, a;
if (feature.symbol) {
newFeature.symbol = feature.symbol;
}
// if the length of attributes required for rendering is 0, return it.
if (passTheseAttributes.length === 0) {
return newFeature;
}
for (a in feature.attributes) {
// if feature attribute is in the list of attributes to pass, add it to the new feature
if (passTheseAttributes.indexOf(a) > -1) {
newFeature.attributes[a] = feature.attributes[a];
}
}
return newFeature;
};
cleanFeatures = arrayUtils.map(layer.featureSet.features, featureCleaner);
return {
layerDefinition: layer.layerDefinition,
featureSet: {
geometryType: layer.featureSet.geometryType,
features: cleanFeatures
}
};
}
/**
* Intercepts all ESRI requests, and cleans data from any containing "Web_Map_as_JSON" property
* @function cleanWebMapAsJSON
* @param {object} request - request object sent that may be sent to ArcGIS Server.
*/
function cleanWebMapAsJSON (request) {
var WebMapAsJSON, i, layer;
if (!request.content || !request.content.Web_Map_as_JSON) {
return request;
}
try {
// get web map JSON data
WebMapAsJSON = JSON.parse(request.content.Web_Map_as_JSON);
if (WebMapAsJSON.hasOwnProperty("operationalLayers") && WebMapAsJSON.operationalLayers.length > 0) {
// step back through each operational layer to see if they are required for viewing.
for (i = WebMapAsJSON.operationalLayers.length - 1; i > -1; i--) {
// get operational layer JSON so that reviwing the following steps will be easier to understand
layer = WebMapAsJSON.operationalLayers[i];
// if opacity = 0 (not visible), remove from the list and go to the next item;
if (layer.hasOwnProperty("opacity") && layer.opacity <= 0) {
WebMapAsJSON.operationalLayers.splice(i, 1);
continue;
}
// if layer has visibleLayers array, but the array is empty, remove from list.
if (layer.hasOwnProperty("visibleLayers") && (layer.visibleLayers.length < 1 || layer.visibleLayers[0] === -1)) {
WebMapAsJSON.operationalLayers.splice(i, 1);
continue;
}
// if layer has a featureCollection, and that featureCollection has an empty layers list, remove it.
if (layer.hasOwnProperty("featureCollection") && layer.featureCollection.layers.length < 1) {
WebMapAsJSON.operationalLayers.splice(i, 1);
continue;
}
if (layer.hasOwnProperty("featureCollection") && layer.featureCollection.layers.length > 0) {
WebMapAsJSON.operationalLayers[i].featureCollection.layers = arrayUtils.map(layer.featureCollection.layers, cleanFeatureCollectionLayer);
}
}
}
// serialize web map json back to string after it has been manipulated;
request.content.Web_Map_as_JSON = JSON.stringify(WebMapAsJSON);
} catch (err) {
console.log(err);
} finally {
return request;
}
}
var clazz = {
/**
* Called when application loads this module
* @method load
* @param {string} [id] - optional string passed when plugin is loaded
* @param {function} require - AMD require function if necessary
* @param {function} callback - callback function to call when this has finished setting up.
*/
load: function (id, require, callback) {
try {
esriRequest.setRequestPreCallback(cleanWebMapAsJSON);
callback(true);
} catch (err) {
callback(err);
}
}
};
return clazz;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment