|
POST
|
I enjoy it all. Tech sessions are great to get it from the horses mouth, but I really enjoy the user presentations. Tech sessions always look good scripted, but I want to see how stuff actually gets used and what gotchas other users may have come across. Of course I'm really interested in the web stuff, but I'm also hoping to see some cool stuff on how people are using the current tech. I'm looking to see what the native devs are doing. I'm also hoping to get an idea of what issues others may be running into. What are the pain-points? What are their obstacles? What do they want to learn? I've met lots of great people at the DevSummit over the years (inlcuding you Chris!) and always look forward to meeting more. I'm pretty much available to talk and I'll be hanging out for a couple of nights when I'm not driving to and from Palm Springs (yay for living reasonably close). I'll also have a few copies of my book to hand out at the conference during my presentation (I think it was accepted, it's always a surprise).
... View more
02-12-2015
12:40 PM
|
1
|
1
|
2376
|
|
POST
|
What may help you out is that in the ArcGIS JavaScript API, with the layers (and other places sometimes), it saves the parameters passed to it in a property called _params. So layer._params will have the original options that were used to create the layer, minus the url. You could use it to create the new Layer. I would use the clone method of dojo/_base/lang to prevent any overwriting of the parameters the layer may try and do. Just to be safe. That's one of those "use at your own risk, underscored property/methods are undocument" type things, but it should help out with what you are doing.
... View more
02-12-2015
10:15 AM
|
0
|
0
|
3167
|
|
POST
|
Adding the layers from one map to another causes issues. You'll want to set it up to create new layers using the same URLs from the existing layers and any options or renderers you may have used and then add the new layers to the second map. You can do checks of what type of layer it is using the instanceof operator. The layers should also have a declaredClass property you can check to see what the type of layer is as well. For reference, this is how the OverviewMap does it.
... View more
02-12-2015
09:19 AM
|
0
|
2
|
3167
|
|
BLOG
|
Thanks Chris. Fixed. If more clarification is needed on something let me know and I can update the post.
... View more
02-11-2015
09:57 AM
|
1
|
0
|
1344
|
|
BLOG
|
Ok, let's talk the ToC. Adding a Table of Contents/Legend widget to ArcGIS web maps is one of those things that unfortunately is a necessary evil. I really think you should strive to design your map and your application in such a way that a ToC isn't needed. But sometimes, in those worst times, you have to do what you have to do. I'm guilty of it. I'm aware that users may want it and developers have to deal with it. I even added an example in a chapter to my ArcGIS WebDev book. Questions in the forum always seem to pop up about it. This ToC Widget from nilu appears to be pretty popular. It's a neat widget, tons of features, generally good stuff. Learn to walk the ToC But you as a developer should have an idea of how a ToC widget is built. I explain the concepts in the above linked sample chapter from my book. But here are the basic steps. Make a request to the legend endpoint of the MapService. Parse the legend response into a sweet looking list of the layers Wire up click events to turn layers on/off Bonus - Wire up click events to sub layers on/off Do the happy dance! That's all there is to it. Simple right? There is probably a dozen different ways you could accomplish this. You could use the dijit/Menu, you could a dijit/Tree, you could just use regular DOM elements, take your pick. Here is some code that does just this. define([
'dojo/_base/declare',
'dojo/Deferred',
'dojo/on',
'dojo/topic',
'dojo/query',
'dojo/dom',
'dojo/dom-attr',
'put-selector',
'dojo/dom-class',
'dojo/Evented',
'esri/lang',
'./layerservice',
'dojox/lang/functional/curry',
'dijit/_WidgetBase',
'dijit/_TemplatedMixin',
'dojo/text!./templates/layertoc.tpl.html'
], function(
declare, Deferred, on, topic,
query, dom, domAttr, put, domClass,
Evented, esriLang,
getLayers, curry,
_WidgetBase, _TemplatedMixin,
template
) {
var labelName = curry(function(a, b) {
if (b.label && b.label.length > 1) {
return b.label;
} else if (a.layerName && a.layerName.length) {
return a.layerName;
} else {
return 'Layer Item';
}
});
var sub = esriLang.substitute;
var layertitle = '<span class="pull-right">${title}</span>';
return declare([_WidgetBase, _TemplatedMixin, Evented], {
templateString: template,
postCreate: function() {
var node = dom.byId('map_root');
put(node, this.domNode);
var map = this.get('map');
var layerIds = this.get('layerIds');
// map over the layer ids and pull
// the layers designated as part of legend
this.tocLayers = map.layerIds.map(function(x) {
if (layerIds.indexOf(x) > -1) {
return map.getLayer(x);
} else {
return false;
}
}).filter(function(a) { return a; });
// map over those layers and create some DOM element containers
this.tocLayers.map(function(x) {
var visible = x.visible ? 'glyphicon-ok' : 'glyphicon-ban-circle';
var panel = put(this.tocInfo, 'div.panel.panel-default');
var pheading = put(panel, 'div.panel-heading');
var ptitle = put(pheading, 'h4.panel-title');
put(
ptitle,
'span.glyphicon.' + visible +
'.layer-item[data-layer-id=' + x.id + ']'
);
var node =
put(ptitle,
'span',
{ innerHTML: sub(x, layertitle) }
);
this._getDetails(x, node, panel);
}.bind(this));
// this will handle turning the whole service on/off
var layerHandle = on(this.tocInfo, '.layer-item:click', function(e) {
e.preventDefault();
e.stopPropagation();
domClass.toggle(e.target, 'glyphicon-ok glyphicon-ban-circle');
var id = domAttr.get(e.target, 'data-layer-id');
var lyr = map.getLayer(id);
lyr.setVisibility(!lyr.visible);
});
// this will turn individual layers on/off
var itemHandle = on(this.tocInfo, '.sublayer-item:click', function(e) {
e.preventDefault();
e.stopPropagation();
domClass.toggle(e.target, 'glyphicon-ok glyphicon-ban-circle');
var id = domAttr.get(e.target, 'data-layer-id');
var subid = parseInt(domAttr.get(e.target, 'data-sublayer-id'));
var lyr = map.getLayer(id);
var lyrs = lyr.visibleLayers;
var visibleLayers = [];
// this bit will adjust the visible layers based on what was clicked
if (lyrs.indexOf(subid) > -1) {
visibleLayers = lyrs.filter(function(x) {
return x !== subid;
});
} else {
visibleLayers = lyrs.concat([subid]);
}
lyr.setVisibleLayers(visibleLayers);
});
this.own(layerHandle, itemHandle);
},
// do a quick check that a URL has been provided
_getDetails: function(layer, node, panel) {
if (!layer.url) { return; }
var pbody = put(panel, 'div.panel-body');
this._getLegend(layer, pbody);
},
// here is the workhorse
_getLegend: function(layer, pbody) {
var url = layer.url + '/legend';
var id = layer.id;
// this is a just a wrapper module I use for
// esri/request. see source at https://github.com/odoe/esri-layertoc-sample
getLayers(url).then(function(layers) {
var tbl = put(pbody, 'table.table');
// iterate over the layers and
// add items to the table
layers.map(function(a) {
var lbl = labelName(a);
var layerId;
var hasLayerId = false;
if (a.hasOwnProperty('layerId')) {
hasLayerId = true;
layerId = a.layerId;
}
// iterate over the legend and add items
// to the table-row
a.legend.map(function(b) {
var tr = put(tbl, 'tr');
if (hasLayerId) {
hasLayerId = false;
var lyrCheck = put(
'span.glyphicon.glyphicon-ok' +
'.sublayer-item[data-layer-id=' + id + ']' +
'.[data-sublayer-id=' + layerId + ']'
);
put(tr, 'td', lyrCheck);
} else {
put(tr, 'td');
}
var td1 = put(tr, 'td.layer-image');
put(tr, 'td', {
innerHTML: lbl(b)
});
// I just add the base64 image, but you could also
// use the URL to image provided in Legend endpoint
put(td1, 'img', {
src: 'data:image/png;base64,' + b.imageData
});
});
});
}, function(err) { console.debug('error in request', err); });
}
});
}); Woah, that's a lot of code. Hey you wanted to learn about a ToC widget, that's going to take a bit of code. I added some comments in there to help you out. You might be able to break out some of the functionality into smaller modules, but I'll leave that up to you. I'm using the put-selector in this sample to create DOM elements (it's included in the ArcGIS JS API) just because I've found it makes more sense for me when composing DOM creation. I'm also using Bootstrap to make it look nice, which is where some of the css class names are defined. When it's all said and done, this sample will look something like this. Pretty snazzy What this does is turns off individual services and the individual layers in the visibleLayers. This sample is only set up for an ArcGISDynamicMapServiceLayer, but you could tweak it for FeatureLayers and if you're bold add support for custom renderers. I try to avoid this when I can as I always seem to muck something up, but it can be done. Good luck. I remember this being a lot harder a long time ago when I did this in Flex, as I don't think the REST API had a Legend endpoint back then, so this is actually easier than it would have been. I just wanted to give you a decent overview of how you can go about accessing the legend endpoint of a map service to pull all the data you need to make your own ToC widget. Maybe this will help you troubleshoot issues you have using other ToC widgets. It's a good exercise in learning to display data in the DOM and sometimes, you may just need a ToC... maybe. The full source code for this sample can be found here. Be sure to check out my blog for more geodev tips and tricks!
... View more
02-11-2015
09:38 AM
|
1
|
6
|
3684
|
|
POST
|
Check out this sample. When you are done moving the vertices, you need to deactivate the toolbar. You'll need to wire up when this happens, in this case the sample deactivates the toolbar on a dbl-click and then applies the edits to the FeatureLayer. function initEditing(evt) {
var firePerimeterFL = map.getLayer("firePerimeterFL");
var editToolbar = new Edit(map);
editToolbar.on("deactivate", function(evt) {
if ( evt.info.isModified ) {
firePerimeterFL.applyEdits(null, [evt.graphic], null);
}
});
var editingEnabled = false;
firePerimeterFL.on("dbl-click", function(evt) {
event.stop(evt);
if (editingEnabled === false) {
editingEnabled = true;
editToolbar.activate(Edit.EDIT_VERTICES , evt.graphic);
} else {
editToolbar.deactivate();
editingEnabled = false;
}
});
} Hope that helps.
... View more
02-09-2015
12:12 PM
|
0
|
1
|
6068
|
|
POST
|
Do you have some sample code to get a better idea of what's happening? Are you using the Edit Toolbar? The edits-complete method is only emitted from a FeatureLayer after you use the applyEdits method.
... View more
02-09-2015
11:13 AM
|
0
|
3
|
6068
|
|
BLOG
|
So far I have not noticed any performance or memory issues. It's basically equivalent to what you are probably already doing, but with the extent graphic and linked panning/zooming already built in. My next task was to try and change the little arrow graphic used to toggle the OverviewMap, I just haven't gotten that far yet.
... View more
02-04-2015
11:14 AM
|
1
|
0
|
564
|
|
BLOG
|
Oh the mighty OverviewMap. This is a classic Dijit in the ArcGIS API for JavaScript. I'm a little torn on the usefulness of an OverviewMap. On one hand, I never include it an app by default and 95% of the time, no one ever asks for it. But, there is always that 5%. I personally don't think it adds much to a map application, it sort of falls into the same category as keeping a zoom history. It's a carry-over from early days that at I think at some point all Esri devs just kind of decided to quietly let die. You do what you have to do Every now and then though, a valid use case comes up. For example, let's say you are managing a fleet of vehicles and you want to focus on a particular neighborhood in your application, but you'd still like to have an overview of the vehicles somehow. In this case, an OverviewMap could do just fine. So you try it only to realize you can't add layers to the OverviewMap. If you look at the docs, this widget is so old it doesn't even dispatch any events to hook into. Sure you can change the basemap, but not much else. But you're a developer, you're not going to let a silly thing like documentation dictate what you can do! Embrace the aspect There's a module in Dojo called dojo/aspect. The aspect module is similar to dojo/_base/connect (don't use this module anymore), but better. The aspect module can listen for methods that occur on an object and do something when they occur. Let that sink in for a second. It's like a catch-all tool to hack away with code you didn't write. Don't abuse it too much, but it can prove very useful at times. After some poking around, I was able to find that the OverviewMap has a method called _activate that occurs when the map object of the OverviewMap is ready and is assigned to a (undocumented) property called overviewMap (thanks Yann Cabon). You can wait for this method to occur and interact with the overviewMap as you would with any map. Go nuts So how would you do this? Here is some sample code where you can use a different basemap and add some census data to the OverviewMap. var fl = new FeatureLayer(blockPointsUrl);
var baseLayer = new ArcGISTiledMapServiceLayer(basemapUrl);
var overviewMapDijit = new OverviewMap({
map: map,
baseLayer: baseLayer,
visible: true
});
var h = aspect.after(overviewMapDijit, '_activate', function() {
h.remove();
overviewMapDijit.overviewMap.addLayer(fl);
});
overviewMapDijit.startup(); So you basically need to wait for the _activate method of the OverviewMap to occur and at that point the overviewMap property of the widget will be ready for you to interact with and you can add other layers to it. Here is a JSBIN demo of this in action. Hack your way to glory Don't let a silly thing like lack of documentation or little roadblocks like not having events to listen for stop you from hacking away at modules in the ArcGIS API for JavaScript. I'm not saying rip it apart, but you can totally work within the confines of the framework while you extend some functionality. Have fun with it and experiment. For more geodev tips and tricks, check out my blog!
... View more
02-04-2015
07:00 AM
|
3
|
3
|
1889
|
|
POST
|
The code in this sample a little old, as I think ItemFileReadStore is deprecated, but I was able to get it to work by removing the "identifier" in your data. I think the "identifier" has to a numeric field... I think. This worked for me var query = new esri.tasks.Query();
query.where = "1=1";
query.returnGeometry = false;
query.returnDistinctValues = true;
query.outfields = ["FIELD_NAME"];
//query.orderByFields = ["FIELD_NAME"]; // only works in 10.1 services, this one is 10.01
getList.queryFeatures(query, function (featureSet) {
//Populate dropdown list
var values = dojo.map(featureSet.features, function (feature) {
return {
name: feature.attributes.FIELD_NAME
};
});
var dataItems = {
label: 'name',
items: values
};
var store = new dojo.data.ItemFileReadStore({
data: dataItems
});
... That populated the dropdown with the field names. Here is the docs on Combox with samples using the dojo/store to populate the dropdown.
... View more
02-03-2015
12:29 PM
|
0
|
1
|
1071
|
|
POST
|
Yeah, Web ADF is not the recommended way to develop new projects. For web development you should be focusing on the ArcGIS API for JavaScript. The ADF isn't even listed in the developers site, so that right there is a signal to stay far away from it.
... View more
02-03-2015
07:11 AM
|
1
|
1
|
1390
|
|
POST
|
You're going to want to use webMercatorUtils to convert the pt to match the GeocodeServer. That should work in most cases.
... View more
02-02-2015
10:56 AM
|
1
|
2
|
2467
|
|
POST
|
You can grab the centroid of the polygon geometry and use that with the Locator task to find the address. You'll want to use the locationToAddress method. It would look something like this //somewhere add listener
tb = new Draw(map);
tb.on("draw-end", addGraphic);
// listener method
function addGraphic(evt) {
var pt = evt.geometry.getCentroid();
locator.locationToAddress(pt, 100).then(function(addresses) {
console.debug('Address Results', addresses);
});
map.graphics.add(new Graphic(evt.geometry, symbol));
} I tried making a JSBIN to demonstrate, but you need to add a proxy to use the Locator Task service, so it won't work in entirely, but should give you a good start. Hope that helps
... View more
02-01-2015
10:46 AM
|
0
|
4
|
2467
|
|
POST
|
Your query seems to be missing a where property. You can also set the query.text, but I always felt it was safer to be explicit and use the where property. If you wanted all results, send a where of "1=1"; query.where = "1=1"; Here is a sample from the Esri site using QueryTask and Query Query data without a map | ArcGIS API for JavaScript
... View more
01-30-2015
01:36 PM
|
1
|
0
|
2254
|
|
POST
|
Thanks! Odd it didn't work, but you could hack together that outFields array and try it the way you have in your example. Something like: var outFields = Object.keys(feature.attributes);
//var outFields = Object.keys(features[0].attributes); //> I would do this when you first get results
return {
"id": feature.attributes[outFields[0]],
"NAME": feature.attributes[outFields[1]]
}; If you are using an older version of IE, you could use dojox/lang/functional/object to get the keys. It's a little odd to do it that way but I think that would definitely work. maybe
... View more
01-30-2015
12:52 PM
|
1
|
1
|
3527
|
| Title | Kudos | Posted |
|---|---|---|
| 2 | yesterday | |
| 1 | 3 weeks ago | |
| 2 | 2 weeks ago | |
| 2 | 05-19-2026 02:12 PM | |
| 1 | 04-24-2026 11:01 AM |
| Online Status |
Online
|
| Date Last Visited |
6 hours ago
|