Hi,
I am adding popups to my application and followed the sample
http://developers.arcgis.com/javascript/sandbox/sandbox.html?sample=popup_chart
In that sample, when you click on a location close to the edge of the map, it puts the popup automatically on the inside. In my case, it does not do that properly, and sometimes, the popup is outside the map and therefore gets partially cut. This happens mostly when I click on the right side of the map. It put the popup to the right of where I clicked instead of to the left as expected. Any idea what is causing this behavior?
Thanks,
Paul
Paul,
could you post your code?
Thanks,
Tim
Hi,
Here is the code. We are using a MVVM model with KnockoutJS
popupV.js:
(function() {
'use strict';
define(['gcviz-vm-datagrid'
], function(datagridVM) {
var initialize;
initialize = function($mapElem) {
var $popup,
popupWindow,
config = $mapElem.datagrid,
mapid = $mapElem.mapframe.id;
$mapElem.find('#' + mapid).append('<div id="popup' + mapid + '" class="gcviz-popup"></div>');
$popup = $mapElem.find('.gcviz-popup');
return(datagridVM.initialize($popup, mapid, config));
};
return {
initialize: initialize
};
});
}).call(this);
popupVM.js:
(function() {
'use strict';
define(['knockout',
'gcviz-i18n',
'gcviz-func',
'gcviz-gismap'
], function(ko, i18n, gcvizFunc, gisMap) {
var initialize,
vm;
initialize = function($mapElem, mapid, config) {
// data model
var datagridViewModel = function($mapElem, mapid, config) {
var _self = this,
layerInfo = config.layers,
popupid = 'popup' + mapid;
_self.init = function() {
var mymap = gcvizFunc.getElemValueVM(mapid, ['map', 'map'], 'js');
if (config.enable) {
// Are popups desired?
for (var i=0; i < layerInfo.length; i++) {
if (layerInfo.popups) {
gisMap.addPopup(mymap, layerInfo);
}
}
}
return { controlsDescendantBindings: true };
};
_self.clickPrevious = function() { //to be coded later };
_self.clickNext = function() { //to be coded later };
_self.init();
};
vm = new datagridViewModel($mapElem, mapid, config);
ko.applyBindings(vm, $mapElem[0]); // This makes Knockout get to work
return vm;
};
return {
initialize: initialize
};
});
}).call(this);
addPopup function inside gisMap module referenced inside popupVM:
addPopup = function(mymap, layerInfo) {
var fill = new esriFill('solid', null, new esriColor('#A4CE67')),
i,
layer,
thedescription,
template,
thetitle,
popup = new esriPopup({
fillSymbol: fill,
titleInBody: true
}, domConstruct.create('div'));
//Add the dark theme
domClass.add(popup.domNode, 'dark');
//Hide the maximize button
domClass.add(popup.domNode.childNodes[0].childNodes[0].childNodes[0].childNodes[4], 'hidden');
//Add popup to map
mymap.infoWindow = popup;
if (layerInfo.popups.title.usefield) {
thetitle = '{' + layerInfo.popups.title.titlefield + '}';
} else {
thetitle = layerInfo.popups.title.titletext;
}
//Put the desired fields in the content description
thedescription = '<table style=\"text-align: left;\">';
//TODO: Add it i18...
thedescription += '<tr><th>Property</th><th>Value</th></tr>';
for (i=0; i < layerInfo.popups.fields.length; i++) {
thedescription +='<tr>';
thedescription += '<td>' + layerInfo.popups.fields.fieldlabel + ':</td>';
thedescription += '<td>{' + layerInfo.popups.fields.fieldname + '}</td>';
thedescription +='</tr>';
}
thedescription += '</table>';
//Setup the template
template = new esriPopupTemplate({
title: thetitle,
description: thedescription
});
//Attach the template to the layer
//Check if in feature layers
for (i=0; i < mymap.layerIds.length; i++) {
layer = mymap.getLayer(mymap.layerIds);
if (layer.id === layerInfo.layerid) {
layer.infoTemplate = template;
}
}
//Attach the template to the layer
//Check if in a GraphicLayer
for (i=0; i < mymap.graphicsLayerIds.length; i++) {
layer = mymap.getLayer(mymap.graphicsLayerIds);
if (layer.id === layerInfo.layerid) {
layer.infoTemplate = template;
}
}
};
popup.css:
@import "gcviz-mixin";
.gcviz-popup {
width: 350px!important;
height: 200px!important;
}
.infowindow {
width: 350px!important;
height: 200px!important;
}
/* Change color of icons in Popups */
.esriPopup.dark div.titleButton,
.esriPopup.dark div.titlePane .title {
color: $white!important;
}
.esriPopup.dark .titlePane {
background-color: $black;
background-image: url("http://s-bsc-geoappint.nrn.nrcan.gc.ca/GeoCanViz/gcviz/images/headBlackbar.png")!important;
}
.esriPopup.dark .actionsPane {
color: $black!important;
background-color: $palegrey;
background-image: url("http://s-bsc-geoappint.nrn.nrcan.gc.ca/GeoCanViz/gcviz/images/footGreybar.png")!important;
}
.esriPopup.dark .action {
color: $black!important;
}
.esriPopup.dark .titlePane, .dj_ie7 .esriPopup.dark .titlePane .title, .esriPopup.dark .contentPane, .esriPopup.dark .actionsPane {
width: 350px!important;
}
.esriPopup.dark .sizer {
width: 350px!important;
}
/* Additional customizations */
.esriPopup.dark .esriPopupWrapper {
border: none!important;
width: 350px!important;
background-color: $black;
}
.esriPopup .contentPane {
text-align: center!important;
background-color: $white!important;
max-height: 150px!important;
color: $black!important;
@include app-text(1.0, bold, $black);
width: 325px!important;
}
.esriViewPopup .gallery {
margin: 0 auto!important;
}
.esriPopup {
z-index: 999999!important;
color: $black!important;
background-color: $white!important;
width: 350px!important;
}
Here are images showing what is happening. One image shows the problem and the other shows when things are ok.
I think this is just default behavior from the API, which is unfortunate. This has been happening to folks for years (myself included). I thought that the API team had plans on trying to address this but they haven't so far.
Here's an old thread which offers a solution that worked for some folks. It didn't for me.
If this InfoWindow always misbehaves, is there a way to always display it in the same location, i.e.: in the lower left corner say?
Yes- I think you could do this. In the other thread I linked, there was a particular line:
map.infoWindow.show(evt.screenPoint, esri.dijit.InfoWindow.ANCHOR_UPPERRIGHT);
That specifies where the infoWindow should appear (map location + relative location based on map location).
In order to always show the infoWindow in the lower left corner, you would simply need to calculate what the map coordinate is for the lower left corner of the map and pass that as the first parameter in the code above. I haven't tried this, though.