I am attemtping to call a dojo tab container within an ESRI pop-up. The code that I have (see below) is able to create a pop-up with a tab container and the contents, but also creates three 'dead' dropdown menus. Is there a way to create the pop-up without the dropdown menus?
var map;
var resizeTimer;
var identifyTask,identifyParams;
function init() {
//setup the popup window
var popup = new esri.dijit.Popup({
fillSymbol: new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([255,0,0]), 2), new dojo.Color([255,255,0,0.25]))
}, dojo.create("div"));
map = new esri.Map("map",{
infoWindow:popup,
});
dojo.connect(map,"onLoad",mapReady);
//Add the imagery layer to the map. View the ArcGIS Online site for services
//http://arcgisonline/home/search.html?t=content&f=typekeywords:service
var basemap = new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer");
map.addLayer(basemap);
var landBaseLayer = new esri.layers.ArcGISDynamicMapServiceLayer("http://<someServer>/ArcGIS/rest/services/test/MapServer");
map.addLayer(landBaseLayer)
}
function mapReady(map) {
dojo.connect(map,"onClick",executeIdentifyTask);
//create identify tasks and setup parameters
identifyTask = new esri.tasks.IdentifyTask("http://<someServer>/ArcGIS/rest/services/test/MapServer");
identifyParams = new esri.tasks.IdentifyParameters();
identifyParams.tolerance = 3;
identifyParams.returnGeometry = true;
identifyParams.layerIds = [0];
identifyParams.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_ALL;
identifyParams.width = map.width;
identifyParams.height = map.height;
//resize the map when the browser resizes
dojo.connect(dijit.byId('map'), 'resize', map,map.resize);
}
function executeIdentifyTask(evt) {
identifyParams.geometry = evt.mapPoint;
identifyParams.mapExtent = map.extent;
var deferred = identifyTask.execute(identifyParams);
deferred.addCallback(function(response) {
// response is an array of identify result objects
// Let's return an array of features.
return dojo.map(response, function(result) {
var feature = result.feature;
feature.attributes.layerName = result.layerName;
console.log(feature.attributes.OBJECTID);
var template = new esri.InfoTemplate();
template.setTitle("</b>Hello World</b>");
template.setContent(getWindowContent);
feature.setInfoTemplate(template);
return feature;
});
});
// InfoWindow expects an array of features from each deferred
// object that you pass. If the response from the task execution
// above is not an array of features, then you need to add a callback
// like the one above to post-process the response and return an
// array of features.
map.infoWindow.setFeatures([ deferred ]);
map.infoWindow.show(evt.mapPoint);
}
function getWindowContent(graphic) {
//make a tab container
var tc = new dijit.layout.TabContainer({ });
return tc.domNode;
}
dojo.addOnLoad(init);
It appears changing the TabContainer code to the following will fix the issue:
var tc = new dijit.layout.TabContainer({
style: "width:100%;height:100%;",
useMenu: false,
useSlider: false,
}, dojo.create('div'));
Related
I'm showing using a bing map on my web page and I'm trying to use a custom pin for the location but it won't show up. My project is ASP.Net Core, My image is stored in wwwroot/images and this JavaScript is in wwwroot/js/site.js. I'm not sure if my path is just wrong or what.
var renderRequestsMap = function (divIdForMap, requestData) {
if (requestData) {
var bingMap = createBingMap(divIdForMap);
addRequestPins(bingMap, requestData);
}
}
function createBingMap(divIdForMap) {
var map = new Microsoft.Maps.Map(
document.getElementById(divIdForMap), {
credentials: BingMapKey,
zoom: 2
});
// tile url from Iowa Environmental Mesonet of Iowa State University
var urlTemplate = 'https://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-{timestamp}/{zoom}/{x}/{y}.png';
var timestamps = ['900913-m50m', '900913-m45m', '900913-m40m', '900913-m35m', '900913-m30m', '900913-m25m', '900913-m20m', '900913-m15m', '900913-m10m', '900913-m05m', '900913'];
var tileSources = [];
for (var i = 0; i < timestamps.length; i++) {
var tileSource = new Microsoft.Maps.TileSource({
uriConstructor: urlTemplate.replace('{timestamp}', timestamps[i])
});
tileSources.push(tileSource);
}
var animatedLayer = new Microsoft.Maps.AnimatedTileLayer({ mercator: tileSources, frameRate: 500 });
map.layers.insert(animatedLayer);
return map;
}
function addRequestPins(bingMap, requestData) {
var locations = [];
$.each(requestData, function (index, data) {
var location = new Microsoft.Maps.Location(data.lat, data.long);
locations.push(location);
var order = index + 1;
alert(data.pinurl);
var pin = new Microsoft.Maps.Pushpin(location, { icon: 'images/low-risk-south-pin.png' });
bingMap.entities.push(pin);
});
var rect = Microsoft.Maps.LocationRect.fromLocations(locations);
bingMap.setView({ bounds: rect, padding: 80 });
}
Also when the map loads it is super zoomed into my pin and whatever I do I can't get it to start with a far out zoom.
If you can, take a look at the network trace. Here you should see where the images are being requested from and will help you verify if it is requesting from the right location.
As for the zooming, you are calculating in the LocationRect from the locations of the pins and then setting the map view based on that. Sounds like that is working as expected. If you don't want to zoom in on your pins, remove that code.
I have a function prototype that loads data from a path. The trick is that I need to change the path afterward. I tried call, apply, bind and even assign but as I am a novice I did not find the solution.
Here a sample of my code :
Chat.prototype.loadMessages = function() {
this.messagesRef = this.database;
var setMessage = function(data) {
var val = data.val();
this.displayMessage(data.key, val.name, val.text);
}.bind(this);
};
var chat = new Chat
function setPath (newpath) {
chat.loadMessages.messageRef = newpath; // I guess, it is where I'm wrong...
chat.loadMessages(); // It should load messages from the new path in my chat container.
}
As I said I also tried :
chat.loadMessages.call(newpath);
or
var setPath = function(newpath) {
chat.loadMessages(newpath);
}.bind(chat);
setPath();
chat.loadMessages();
But the chat container continues to disclose messages from the old path...
This looks a bit convoluted. Just pass messagesRef as a parameter and make it default to this.database:
Chat.prototype.loadMessages = function(messagesRef = this.database) {
// do whatever is needed with messagesRef
};
chat = new Chat();
chat.loadMessages(); // load from the default location
chat.loadMessages('foobar'); // load from this specific location
It looks like you are creating a function with loadMessages, which is fine but you need to pass in a value to set the new path. Is this more of what you were thinking?
Chat.prototype.loadMessages = function (newPath) {
this.messagesRef = newPath || this.database; // if newPath is empty than default to this.database
var setMessage = function(data) {
var val = data.val();
this.displayMessage(data.key, val.name, val.text);
};
var chat = new Chat
function setPath (newpath) {
chat.loadMessages(newpath);
}
I have developed a 3D viewer of buildings. What I'm trying to add now is the selection of the content of a WMS (Web Map Service) below the building entities.
Basically, I want to be able to select the building at the position were the user left clicks. The colour of the building should change (which works). And I want to retrieve the information of the Web Map Service at the position were the user clicked.
This is what I have coded so far:
var pickColor = Cesium.Color.CYAN.withAlpha(0.7);
var selectedEntity = new Map();
handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function(click) {
var pickedObject = viewer.scene.pick(click.position);
if (Cesium.defined(pickedObject)) {
var entityId = pickedObject.id._id;
var oldColor = buildingMap.get(entityId).polygon.material.color;
buildingMap.get(entityId).polygon.material.color = pickColor;
selectedEntity.set(entityId, oldColor);
var currentLayer = viewer.scene.imageryLayers.get(1);
if (typeof currentLayer !== 'undefined') {
var info = currentLayer._imageryProvider._tileProvider.getTileCredits(click.position.x, click.position.y, 0);
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
However, my variable "info" stays undefined, whereas I expect it to return an array.
For WMS you need to use the wms GetFeatureInfo capability:
var pickRay = viewer.camera.getPickRay(windowPosition);
var featuresPromise = viewer.imageryLayers.pickImageryLayerFeatures(pickRay, viewer.scene);
if (!Cesium.defined(featuresPromise)) {
console.log('No features picked.');
} else {
Cesium.when(featuresPromise, function(features) {
// This function is called asynchronously when the list if picked features is available.
console.log('Number of features: ' + features.length);
if (features.length > 0) {
console.log('First feature name: ' + features[0].name);
}
});
}
I have trouble about selecting the feature layer based on its attribute. I got this code below but it says:
Uncaught TypeError: Cannot read property 'features' of undefined
here's my code:
var init = function () { // A function that will initialize and execute all the declared variables
var geographic = new OpenLayers.Projection("EPSG:4326"); // Setting the standard geographic projection
var mercator = new OpenLayers.Projection("EPSG:3857"); // Setting the universal geographic projection
map = new OpenLayers.Map('map'); // Creating & initializing map constructor
var base_osm = new OpenLayers.Layer.OSM("OpenStreetMap"); // Setting OpenStreetMap as a BaseMap
map.addControl(
new OpenLayers.Control.MousePosition({
prefix: '<small style="color:blue">',
suffix: '</small>',
numDigits: 2,
emptyString: '<small style="color:red">' + 'Mouse is not over map.' +'</small>'
})
);
var layer_agao = new OpenLayers.Layer.Vector("Agao");
map.addLayers([layer_agao, base_osm]); // Adding the vector layer to the map
map.addControl(new OpenLayers.Control.LayerSwitcher());
selectControl = new OpenLayers.Control.SelectFeature(layer_agao, {
onSelect: onFeatureSelect, onUnselect: onFeatureUnselect
});
map.addControl(selectControl);
selectControl.activate();
map.setCenter(new OpenLayers.LonLat(13975400.3513, 999830.692078),16);
var format_agao = new OpenLayers.Format.GeoJSON(); //initializing and calling the rendered GeoJSON Layer from views.py
var feat_agao = format_agao.read({{agao_transform|safe}});
layer_agao.addFeatures(feat_agao);
layer_agao.events.on({
featureselected: function(event) {
var feature = event.feature;
var area = feature.geometry.getArea();
var id = feature.attributes.newpin;
var output = "Land Pin: " + id + "<br/>" + "Area: " + area.toFixed(12);
document.getElementById("status").innerHTML = output;
}
});
init.showparcel();
}
init.showparcel = function (getpin){
for(var f=0;f<layer_agao.features.length;f++) {
if(layer_agao.features[f].attributes.newpin == getpin) {
selectControl.select(layer_agao.features[f]);
break;
}
}
}
I also read about getfeaturesbyattribute, but i can't find any example. So, is there other way to call the specific feature layer on click (event)? This is for my searching...
You would need to use the getFeaturesByAttribute or track features in your own index with their FID as the index of that object, and then use getFeatureByFid.
I usually prefer to track them in my own object or hashtable and then reference by FID.
In your example I would pull in an unique id on the attribs that you can search yourself outside of openlayers, and then use the getFeaturesByAttribute to reference the unique id that you know exist. If that doesn't may sense hit me up in the comments.
vlayer.getFeaturesByAttribute("fid", target)[0]
http://dev.openlayers.org/docs/files/OpenLayers/Layer/Vector-js.html#OpenLayers.Layer.Vector.getFeaturesByAttribute
The correct way to add a listener to a Vector.Layer is layer.events.register(type, obj, listener) as shown in the comments in the source: http://trac.osgeo.org/openlayers/browser/trunk/openlayers/lib/OpenLayers/Layer/Vector.js. Note, the listener for featureselected is passed the selected feature, not the event as you have it.
So, in your case:
layer_agao.events.on('featureselected', null, function(feature){
//do something with the feature
var area = feature.geometry.getArea();
var id = feature.attributes.newpin;
var output = "Land Pin: " + id + "<br/>" + "Area: " + area.toFixed(12);
document.getElementById("status").innerHTML = output;
});
getFeaturesByAttribute doesn't look like it is what you need, based on your code sample, though it is useful in specific cases.
Basically I'm making a nice and simple mobile web app for a couple of my friends. It uses some online databases to store position data of shops. I've got the databases working like a charm. No problems there. In fact everything is working except it's all happening in the wrong order I think. The data from the database should be stored in an array and then the objects in that array are displayed on screen. However, using some console logs I've found that the data is being displayed, then being retrieved from the database, then the arrays are filled. But no matter what I do, I can't get it to work! Here is my code:
var latOfSpots;
var lngOfSpots;
var nameOfSpots;
var spotArray;
var spotLatLng;
var spotCollection;
var markers;
var Spot;
var spot;
function init() {
//-------------------------- INITIATE SPOT VARIABLES ---------------------------//
map = new google.maps.Map2(document.getElementById("map"));
latOfSpots= new Array(51.14400,51.02295);
lngOfSpots= new Array(0.25721,0.26450);
nameOfSpots= new Array('Tescos', 'Sainsburys');
spotLatLng= new Array();
markers= new Array();
Spot = Parse.Object.extend("Spot");
spot = new Spot();
//----------------- GET DATA FROM THE PARSE.COM DATABASE ---------------------//
//---------------------- DISPLAY ARRAY DATA ON MAP ---------------------------//
GetData();
DisplayData();
//----------------------- SET MAP SETTINGS -----------------------------------//
map.setCenter(spotLatLng[0],8);
//map.addControl(new google.maps.LargeMapControl());
map.addControl(new google.maps.MapTypeControl());
}; //END OF INIT FUNCTION ------------------------------------------------//
google.setOnLoadCallback(init);
//------------------- PRIMARY FUNCTION TO GET DATA FROM DATABASE ---------------//
function GetData()
{
var query = new Parse.Query(Spot);
spotCollection = query.collection();
spotCollection.fetch({
success: function(spotCollection) {
// spotCollection.toJSON()
// will now be an array of objects based on the query
FillArrays();
console.log('data retreived' + spotCollection);
}
});
}
//----------------- FUNCTION TO LOAD DATABASE INTO ARRAYS -------------------//
function FillArrays()
{
spotArray = spotCollection.toJSON();
for (var j = 0; j<spotArray.length; j++)
{
latOfSpots.push(spotArray[j].Latitude);
lngOfSpots.push(spotArray[j].Longitude);
nameOfSpots.push(spotArray[j].Name);
}
}
//------------------------ FUNCTION TO DISPLAY ALL ARRAY DATA ONSCREEN -----------------//
function DisplayData()
{
for(var i = 0; i<latOfSpots.length; i++)
{
spotLatLng[i] = new google.maps.LatLng(latOfSpots[i], lngOfSpots[i]);
for(var x = 0; x<latOfSpots.length; x++)
{
markers[x] = new google.maps.Marker(
spotLatLng[i], {
"draggable":false,
"title":nameOfSpots[i],
});
map.addOverlay(markers[x]);
}
}
console.log('data displayed');
}
Your database query is asynchronous. You need to use the data in the Get_Data callback function (after it has come back from the server). Currently you are attempting to use it before the server sends it back.
//------------------- PRIMARY FUNCTION TO GET DATA FROM DATABASE ---------------//
function GetData()
{
var query = new Parse.Query(Spot);
spotCollection = query.collection();
spotCollection.fetch({
success: function(spotCollection) {
// spotCollection.toJSON()
// will now be an array of objects based on the query
FillArrays();
console.log('data retreived' + spotCollection);
DisplayData();
}
});
}