I'm trying to add a map printout functionality to my javascript 3.27 based map, and I've got a problem with the print functions. In the print script code there is this:
......
Printapp.map = new esri.Map
("map",
{
basemap: "topo",
center: [-102, 54.75],
zoom: 6,
slider: false
}
);
.........
But I already have other script basically to loop through a map service and show the layers with the map type, coordinates and layers on startup. Then I click print, it defaults to this instead of what's on the screen. I can change the zoom level, basemap map type etc. and it will print out the changes instead of what's showing on the screen.
If I comment this bit out, it doesn't work. Basically I just want the print function to print out what's on the current map screen. How do I do this?
Thanks
Hi Robert, yep, I agree, this should be simple...Anyway, This is the code to dynamically load the map layers by looping through the map service:
<script src="https://js.arcgis.com/3.27/"></script>
<script>
//Dynamic layer script. Loops through a map service for all layers and automatically lists them in a map.
var layer, map, mapLegend, visible = [];
require([
"esri/map",
"esri/layers/ArcGISDynamicMapServiceLayer",
"dojo/dom",
"dojo/on",
"dojo/query",
"dojo/_base/array",
"dojo/domReady!"
], function(
Map, ArcGISDynamicMapServiceLayer,
dom, on, query, arrayUtils
) {
map = new Map(
"map",
{basemap: "satellite",
center: [-102, 54.75],
slider: true,
nav: false,
zoom: 6});
//Point the url below to the published mapservice you want to use
layer = new ArcGISDynamicMapServiceLayer("https://xxxxxxx/arcgis/rest/services/Test/DMAF_Application_V3/MapServer",{
"showAttribution": true, "opacity": 0.7, mode: ArcGISDynamicMapServiceLayer.MODE_ONDEMAND,
outFields: ["*"],
});
layer.on("load", buildLayerList);
map.addLayer(layer);
function buildLayerList() {
var items = arrayUtils.map(layer.layerInfos, function(info, index) {
if (info.defaultVisibility) {
visible.push(info.id);
}
return "<input type='checkbox' class='list_item'" + (info.defaultVisibility ? "checked=checked" : "") + "' id='" + info.id + "'' /><label for='" + info.id + "'>" + info.name + "</label>";
});
var ll = dom.byId("layer_list");
ll.innerHTML = items.join(' ');
layer.setVisibleLayers(visible);
on(ll, "click", updateLayerVisibility);
}
function updateLayerVisibility() {
var inputs = query(".list_item");
var input;
visible = [];
arrayUtils.forEach(inputs, function(input) {
if (input.checked) {
visible.push(input.id);
}
});
//if there aren't any layers visible set the array to be -1
if (visible.length === 0) {
visible.push(-1);
}
layer.setVisibleLayers(visible);
}
});
</script>
And this is the print code:
script src="https://js.arcgis.com/3.27/"></script>
<script>
//Print a map script
var Printapp = {};
require([
"esri/map",
"esri/layers/FeatureLayer",
"esri/dijit/Print",
"esri/tasks/PrintTemplate",
"esri/request",
"esri/config",
"dojo/_base/array",
"dojo/dom",
"dojo/parser",
"dijit/layout/BorderContainer",
"dijit/layout/ContentPane",
"dojo/domReady!"
], function(
Map, FeatureLayer,
Print, PrintTemplate,
esriRequest, esriConfig,
arrayUtils, dom, parser
) {
parser.parse();
Printapp.printUrl = "https://xxxxxxxxxxxx/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task";
esriConfig.defaults.io.proxyUrl = "/proxy/";
Printapp.map = new Map("map",
{
basemap: "topo",
center: [-102, 54.75],
slider: true,
nav: false,
zoom: 6});
// add graphics for layers
var layerUrl = "https://xxxxxxxxxxx/arcgis/rest/services/Test/DMAF_Application_V3/MapServer";
var printFeatureLayer = new FeatureLayer(layerUrl, {
"mode": FeatureLayer.MODE_SNAPSHOT
});
Printapp.map.addLayer(printFeatureLayer);
// get print templates from the export web map task
var printInfo = esriRequest({
"url": Printapp.printUrl,
"content": { "f": "json" }
});
printInfo.then(handlePrintInfo, handleError);
function handlePrintInfo(resp) {
var layoutTemplate, templateNames, mapOnlyIndex, templates;
layoutTemplate = arrayUtils.filter(resp.parameters, function(param, idx) {
return param.name === "Layout_Template";
});
if ( layoutTemplate.length === 0 ) {
console.log("print service parameters name for templates must be \"Layout_Template\"");
return;
}
templateNames = layoutTemplate[0].choiceList;
// remove the MAP_ONLY template then add it to the end of the list of templates
mapOnlyIndex = arrayUtils.indexOf(templateNames, "MAP_ONLY");
if ( mapOnlyIndex > -1 ) {
var mapOnly = templateNames.splice(mapOnlyIndex, mapOnlyIndex + 1)[0];
templateNames.push(mapOnly);
}
// create a print template for each choice
templates = arrayUtils.map(templateNames, function(ch) {
var plate = new PrintTemplate();
plate.layout = plate.label = ch;
plate.format = "PDF";
plate.layoutOptions = {
"authorText": "Made by: xxxxxxxxx",
"copyrightText": "<copyright info here>",
"legendLayers": [],
"titleText": "Title",
"scalebarUnit": "Miles"
};
return plate;
});
// create the print dijit
Printapp.printer = new Print({
"map": Printapp.map,
"templates": templates,
url: Printapp.printUrl
}, dom.byId("print_button"));
Printapp.printer.startup();
}
function handleError(err) {
console.log("Something broke: ", err);
}
});
</script>
In the page, the print script is directly under the dynamic map script code, which runs first. The trouble is, in this section in the print script:
Printapp.map = new Map("map",
{
basemap: "topo",
center: [-102, 54.75],
slider: false,
nav: false,
zoom: 6});
it is insisting I have a new map. If I change it or do anything to this the code doesn't work. I have been trying many things, too many to go into details here, but usually the print button disappears or when I click it, nothing happens. Sometimes the generate legend script stops working too. I just want this print code to printout what is showing in the current map view. I have a resizable div section at the bottom of the mapping screen which I'm going to use in future for attribute tables, and when I drag resize it up and down, I can see the topo basemap drawing underneath, which I don't want.
Thanks!
Carl,
So if you are going to use multiple JS files then like I said in a previous reply you can either use a window global variable for the map object or pass the map object directly to your print code when you call the print code:
<script src="https://js.arcgis.com/3.27/"></script>
<script>
//Dynamic layer script. Loops through a map service for all layers and automatically lists them in a map.
var layer, map, mapLegend, visible = [];
require([
"esri/map",
"esri/layers/ArcGISDynamicMapServiceLayer",
"dojo/dom",
"dojo/on",
"dojo/query",
"dojo/_base/array",
"dojo/domReady!"
], function(
Map, ArcGISDynamicMapServiceLayer,
dom, on, query, arrayUtils
) {
window.map = new Map(
"map", {
basemap: "satellite",
center: [-102, 54.75],
slider: true,
nav: false,
zoom: 6
});
//Point the url below to the published mapservice you want to use
layer = new ArcGISDynamicMapServiceLayer("https://xxxxxxx/arcgis/rest/services/Test/DMAF_Application_V3/MapServer", {
"showAttribution": true,
"opacity": 0.7,
mode: ArcGISDynamicMapServiceLayer.MODE_ONDEMAND,
outFields: ["*"],
});
layer.on("load", buildLayerList);
window.map.addLayer(layer);
function buildLayerList() {
var items = arrayUtils.map(layer.layerInfos, function(info, index) {
if (info.defaultVisibility) {
visible.push(info.id);
}
return "<input type='checkbox' class='list_item'" + (info.defaultVisibility ? "checked=checked" : "") + "' id='" + info.id + "'' /><label for='" + info.id + "'>" + info.name + "</label>";
});
var ll = dom.byId("layer_list");
ll.innerHTML = items.join(' ');
layer.setVisibleLayers(visible);
on(ll, "click", updateLayerVisibility);
}
function updateLayerVisibility() {
var inputs = query(".list_item");
var input;
visible = [];
arrayUtils.forEach(inputs, function(input) {
if (input.checked) {
visible.push(input.id);
}
});
//if there aren't any layers visible set the array to be -1
if (visible.length === 0) {
visible.push(-1);
}
layer.setVisibleLayers(visible);
}
});
</script>
<script src="https://js.arcgis.com/3.27/"></script>
<script>
//Print a map script
var Printapp = {};
require([
"esri/layers/FeatureLayer",
"esri/dijit/Print",
"esri/tasks/PrintTemplate",
"esri/request",
"esri/config",
"dojo/_base/array",
"dojo/dom",
"dojo/parser",
"dijit/layout/BorderContainer",
"dijit/layout/ContentPane",
"dojo/domReady!"
], function(
FeatureLayer,
Print, PrintTemplate,
esriRequest, esriConfig,
arrayUtils, dom, parser
) {
parser.parse();
Printapp.printUrl = "https://xxxxxxxxxxxx/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task";
esriConfig.defaults.io.proxyUrl = "/proxy/";
Printapp.map = window.map
// add graphics for layers
var layerUrl = "https://xxxxxxxxxxx/arcgis/rest/services/Test/DMAF_Application_V3/MapServer";
var printFeatureLayer = new FeatureLayer(layerUrl, {
"mode": FeatureLayer.MODE_SNAPSHOT
});
Printapp.map.addLayer(printFeatureLayer);
// get print templates from the export web map task
var printInfo = esriRequest({
"url": Printapp.printUrl,
"content": {
"f": "json"
}
});
printInfo.then(handlePrintInfo, handleError);
function handlePrintInfo(resp) {
var layoutTemplate, templateNames, mapOnlyIndex, templates;
layoutTemplate = arrayUtils.filter(resp.parameters, function(param, idx) {
return param.name === "Layout_Template";
});
if (layoutTemplate.length === 0) {
console.log("print service parameters name for templates must be \"Layout_Template\"");
return;
}
templateNames = layoutTemplate[0].choiceList;
// remove the MAP_ONLY template then add it to the end of the list of templates
mapOnlyIndex = arrayUtils.indexOf(templateNames, "MAP_ONLY");
if (mapOnlyIndex > -1) {
var mapOnly = templateNames.splice(mapOnlyIndex, mapOnlyIndex + 1)[0];
templateNames.push(mapOnly);
}
// create a print template for each choice
templates = arrayUtils.map(templateNames, function(ch) {
var plate = new PrintTemplate();
plate.layout = plate.label = ch;
plate.format = "PDF";
plate.layoutOptions = {
"authorText": "Made by: xxxxxxxxx",
"copyrightText": "<copyright info here>",
"legendLayers": [],
"titleText": "Title",
"scalebarUnit": "Miles"
};
return plate;
});
// create the print dijit
Printapp.printer = new Print({
"map": Printapp.map,
"templates": templates,
url: Printapp.printUrl
}, dom.byId("print_button"));
Printapp.printer.startup();
}
function handleError(err) {
console.log("Something broke: ", err);
}
});
</script>
Are there any examples of how this is done? Seeing some code makes a lot more sense to me than describing what needs to happen - as I said earlier, I'm not a programmer. I have tried calling the map object to the print script but it hasn't worked.
Nevermind. I think I've found some examples. I'll see if I can get this to work.
??? I provided your code fixed for this in my last reply...
Oh yes I see the changes! Sorry, I thought you'd just posted my code back as a quote. It's been a long day. Doh.... Well what you've posted still doesn't work. it says printing when I click on the print button, but it seems to fail silently, with the button going back to Print and no output - similar to what I've been trying. I've even created a new html document with just these two scripts, just in case something was interfering, but nope it still won't print. I've been scouring through the code line by line and I just can't see what's going wrong here
Carl,
So when in the print js file have you console.log ed the map to see if it is a map object?
There is no console log that I can see (I wouldn't know where that would be). I'm writing it in notepad++ and it's not a js file, the scripts all in a single html document (for now).
Carl,
OK. That makes even less sense then. If all your code is in the same html then why do you have the code in seperate script tags?...
I plan on moving them to separate .js files soon. Right now I find that makes it easy to read and see where one script starts and another finishes, and also I'm not fishing in and out of separate .js files all the time. Makes sense. However, this particular problem has been keeping things on hold.