|
POST
|
A QueryTask returns a couple of pieces of info you could use. It returns a fieldAliases array and a fields array. The fields array isn't listed in the docs, but it's on the REST spec. Anyway, you could do something like return {
"id": feature.attributes[featureSet.fields[0].name],
"NAME": feature.attributes[featureSet.fields[1].name]
}; It's a little odd, but that could work.
... View more
01-30-2015
12:20 PM
|
0
|
5
|
3524
|
|
BLOG
|
Esri provides a lot of resources and tools for ArcGIS Developers. You could be working in JavaScript, iOS, Android, or Java, They pretty much have you covered as far as SDKs go. You might be fairly comfortable in the SDK of your choice, but if you ever decided to go from JavaScript to Android, other than the language difference, you should feel pretty good about it. Why? Because it's all based on a single REST API. We're all really saying the same thing Regardless of the SDK you work in, under the hood it's all taking to the same person on the other end of the line, the REST endpoint of an ArcGIS Server, Portal or Online. This unified REST API is why you may have felt pretty familiar moving from Silverlight or Flex to JavaScript. Once you get past the initial language bump, the methods and practices all seem to work the same. A Feature has the same structure no matter what SDK you are using. Editing data is familiar no matter what language you are working in. Sure, some of the tools may differ, but it's all very familiar. SDKs? Where we're going, we don't need SDKs Because the REST API is the driving force to the ArcGIS development, you could theoretically write all your applications from scratch against the API without using any ArcGIS SDKs. Sometimes this becomes necessary when the features in an SDK may not be up to date with the latest features of the REST API. The more familiar you are with working with the REST API, the easier it is for you as a developer to overcome these hurdles. It's for this same reason that you are not limited to having to use the ArcGIS JS API for your JavaScript development, you could use esri-leaflet. Esri-leaflet is able to pull in tiles and services from ArcGIS sources and work with them because under the hood it's speaking the same language as everyone else, the language of the REST API. It may not be as feature rich as the ArcGIS JS API, but it's also much more lightweight and could be perfectly suitable for your use case. Need to interact with ArcGIS Services in a server side application? You can talk to the REST API directly just like this ArcGIS partial class library does. You can run your queries, customize the results and output the information as needed. You don't need to be limited to official SDKs and tools, the REST API is there for your abuse use. Have fun with it So go on, give it a shot. Next time you find yourself limited by the SDK of your choosing, try to see if you can interact with the REST API directly to get the desired results. Up your game and get things done. For more tips and tricks, be sure to check out my geodev blog.
... View more
01-28-2015
07:34 AM
|
3
|
0
|
2591
|
|
POST
|
I created an updated version of the ClusterLayer that works with services, similar to a FeatureLayer, but with same added sugar. You can read more about it here. Esri ClusterFeatureLayer - odoenet Here is a GeoNet blog post here Let's talk clusters. The source code can be found here odoe/esri-clusterfeaturelayer · GitHub
... View more
01-21-2015
11:04 AM
|
0
|
4
|
2640
|
|
BLOG
|
Have you ever been working with your nice and shiny mobile web map and trying to do some sort of drawing or selecting an item on the screen only to realize you can't tell where your fat fingers have touched the map? Wouldn't it be cool if you could somehow get some feedback on how you are interacting with the map? I'll let you in on a dirty secret, it's pretty easy to do. Touchy feely A while ago I had a user comment that they had issues knowing if they were clicking on the map where they thought they were. Touch screens on mobile devices can be finicky sometimes and I have seen some slower devices be off my as much as an inch on where you thought you were touching on the screen. To deal with this, I made a TouchWidget. What this widget does is simply listen for click events on the map and add a little circle, then after half a second or so, delete the marker. The idea isn't too difficult, but it can be a little jarring to just show and hide a marker. So you can use some of the graphics modules in Dojo to make the transition a little nicer. Here is a neat little tutorial on working with Dojo animations. Here is the source code for the TouchWidget define([
'esri/layers/GraphicsLayer',
'esri/graphic',
'esri/symbols/SimpleMarkerSymbol',
'dojo/on', 'dojo/fx', 'dojo/_base/fx', 'dojo/fx/easing',
'dojo/aspect', 'dojo/_base/Color',
'dojo/_base/declare', 'dojo/_base/lang',
'dijit/_WidgetBase', 'dijit/a11yclick'
], function(
GraphicsLayer, Graphic, SimpleMarkerSymbol,
on, fx, coreFx, easing, aspect, Color,
declare, lang, _WidgetBase, a11yclick
) {
'use strict';
var hitch = lang.hitch;
return declare([_WidgetBase], {
postCreate: function() {
this.set('delay', this.settings.delay || 500);
this._symInner = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, this.settings.innerSize, null, new Color(this.settings.innerColor));
this._symOuter = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, this.settings.outerSize, null, new Color(this.settings.outerColor));
this.touchLayer = new GraphicsLayer();
},
startup: function() {
if (!this.map) {
this.destroy();
throw new Error('Must provide a map object to use TouchWidget');
}
if (this.map.loaded) {
this._init();
} else {
on.once(this.map, 'load', hitch(this, '_init'));
},
// widget methods
_fxArgs: function(graphic) {
return {
node: graphic.getNode(),
duration: this.delay,
easing: easing.expoOut
};
},
_fxToCombine: function(graphicOuter, graphicInner) {
return [
coreFx.fadeOut(this._fxArgs(graphicOuter)),
coreFx.fadeOut(this._fxArgs(graphicInner))
];
},
_onAspectAfterEnd: function(graphicOuter, graphicInner) {
return lang.hitch(this, function() {
this.touchLayer.remove(graphicOuter);
this.touchLayer.remove(graphicInner);
});
},
_onTimeOut: function(graphicOuter, graphicInner) {
return hitch(this, function() {
var combined = this._fxToCombine(graphicOuter, graphicInner);
var f = fx.combine(combined);
this.own(aspect.after(f, 'onEnd', hitch(this, this._onAspectAfterEnd(graphicOuter, graphicInner))));
f.play();
});
},
_onTouchClick: function(e) {
var graphicOuter = new Graphic(e.mapPoint, this._symOuter);
var graphicInner = new Graphic(e.mapPoint, this._symInner);
this.touchLayer.add(graphicOuter);
this.touchLayer.add(graphicInner);
setTimeout(hitch(this, this._onTimeOut(graphicOuter, graphicInner)), this.delay);
},
// private methods
_init: function() {
this.map.addLayer(this.touchLayer);
this.set('loaded', true);
this.emit('load', {});
// set up touch handlers
this.own(on(this.get('map'), a11yclick.click, hitch(this, '_onTouchClick')));
}
});
}); What this widget is doing is setting up an inner and outer graphic symbol. The size of these symbols can be defined via the parameters passed to the widget. It also adds it's own layer to display these features so you don't have to worry about conflicting with what may be happening on the default GraphicsLayer of the map. Animating nodes The dojo/fx library doesn't know what a Graphic from the Esri library is, so you'll need to get the actual DOM node of the Graphic to interact with. You can do this via the graphic.getNode() method. Now you can set up a delay using setTimeout to gracefully remove the touch marker from the map. You just need to pass around the graphics in this chain of methods so they are disposed of properly. You can see how this TouchWidget works in this demo. So feel free to touch your maps and get more interactive. Check out my blog for more tips & tricks!
... View more
01-21-2015
07:06 AM
|
0
|
0
|
2375
|
|
POST
|
Haven't tried it with WAB, but can you run nodemon? That will monitor changes to the code and restart node apps.
... View more
01-20-2015
02:25 PM
|
0
|
2
|
6893
|
|
BLOG
|
One of the easiest things you can do to personalize your ArcGIS JavaScript map is to add a custom logo. Esri does it, why can't you? Own it Chances are you're building the app for a client, and a client can mean your own workplace, but I'm betting that client has brand and most likely a logo. You work hard for your maps, so let people know it! This isn't really difficult to do, it's just a little css and DOM insertion, but you could power it up and make it a reusable widget too. A very simple example may look something like this: var LogoWidget = declare([_WidgetBase, _TemplatedMixin], {
templateString: '<div class="${logoClassName}" data-dojo-attach-event="click:openLink"></div>',
postCreate: function() {
put(dom.byId('map_root'), this.domNode);
},
openLink: function() {
window.open(this.get('url'), '_blank');
}
}); What you have is a basic widget where you can use the put-selector to add the widgets DOM node to the page. I'm going to assume you want the logo within the map bounds, so I set it up to insert at the div with an id of "map_root". This is equal to the DOM id you gave to the DOM element you provided for the map, so if the map id is "map", it will contain a div with an id of "map_root". If my map id was "harry", it would contain a div with an id of "harry_root". I'm sure you get the idea. Once you do that, you just initialize the widget with a URL and a class name you define in your css: var logo = new LogoWidget({
url: 'http://odoe.net/blog/',
logoClassName: 'my-logo'
}); Style it Then in the css for the widget you can define the size and location as well as the background-image: .my-logo {
display: inline-block;
position: absolute;
height: 36px;
width: 125px;
right: 75px;
bottom: 5px;
z-index: 30;
background-color: white;
background-image: url('http://odoe.net/blog/wp-content/uploads/logo_gray_sm.png');
cursor: pointer;
} *Note - You could switch all this up to use an <img> tag if you wanted. There you have it! You have a logo in the map and you can click that logo to go to a website of your choosing. You can view a demo of this sample and play around with it if you like. There's nothing stopping you from being obnoxious awesome and adding an animated gif as your logo either. So customize your apps and maps and show off your skills!
... View more
01-14-2015
08:05 AM
|
0
|
0
|
2471
|
|
BLOG
|
If you've used the LabelLayer before to annotate your map you are familiar with the fact that you can add labels that match up with your map data. This is a neat feature and I'm sure it's really cool to work with pseudo-annotations in your webmap, but why stop there? Font Awesome for awesomeness If you've never used Font Awesome, it's a great little CSS Toolkit to add some nice font icons to your web page. This is really useful if you need to build an editor or want to add a little bit of flavor to your site and it's really easy to use. If you've ever added custom fonts to your web page, you know that there's some boilerplate involved. You can get similar icons with Bootstrap and even use them both together. It's also pretty easy to use font icons in Leaflet if you wanted to and I was curious how I could do the same thing with the ArcGIS API for JavaScript. When I first looked at this, there was no LabelLayer in the API yet. I recently had a use-case to use font icons as markers in a project so I dove right in. Turns out, I don't even need the LabelLayer, nor do I care. TextSymbol and Font So how do we accomplish this? With the introduction of the LabelLayer, there were a couple of other support modules added - Font and TextSymbol. These two modules are the key to awesome markers. There are a few steps you need to do to get this working. 1. The first thing you'll want to do is add a reference to the font awesome css to your page. <link href="https://community.esri.com//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet"> 2. Define the Font for your TextSymbol. var font = new Font("20pt", Font.STYLE_NORMAL, Font.VARIANT_NORMAL, Font.WEIGHT_BOLD,"FontAwesome"); 3. Create a TextSymbol. var sym = new TextSymbol("", font, treeColor); What is that weird character I am passing to the TextSymbol? That is the character from Font Awesome I want to use. You'll need to copy and paste the character like any other, but you'll want to use the Font Awesome Cheatsheet for that. 4. Now you can assign the symbol to the graphic and add it to the map. feature.setSymbol(sym);
map.graphics.add(feature); Here is the full JavaScript for the above snippets. require([
"esri/map",
"esri/symbols/TextSymbol",
"esri/tasks/query",
"esri/tasks/QueryTask",
"esri/symbols/Font",
"esri/Color",
"dojo/domReady!"
], function(
Map, TextSymbol,
Query, QueryTask, Font,
Color
) {
var map = new Map("map-div", {
center: [-122.445, 37.752],
zoom: 14,
basemap: "gray"
});
var treeColor = new Color("#666");
var treesUrl = "http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Street_Trees/FeatureServer/0";
var font = new Font("20pt", Font.STYLE_NORMAL, Font.VARIANT_NORMAL, Font.WEIGHT_BOLD,"FontAwesome");
// you can use the cheatseeht to copy paste the font symbol
// http://fortawesome.github.io/Font-Awesome/cheatsheet/
var sym = new TextSymbol("", font, treeColor);
var qTask = new QueryTask(treesUrl);
var query = new Query();
query.outFields = ["*"];
//query.where = "TreeID = 0";
query.where = "1=1";
query.returnGeometry = true;
qTask.execute(query).then(function(featureSet) {
featureSet.features.map(function(feature) {
feature.setSymbol(sym);
map.graphics.add(feature);
});
});
}); Add some flair! The result of doing the above may get you something like this. That's really cool, but it's not quite right. Groups of trees kind of blend right into each other. My inner-cartographer is wincing. It's ok, we can do something about that. The icons are added via an svg <text> tag, which means we can use CSS to style it. text {
text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;
} Now you should get a map that displays the icons like below. BAM! That looks pretty cool if I do say so myself. You find the full demo of this example here. Use it in a renderer Want to use it as a renderer for a FeatureLayer? No problem. require([
"esri/map",
"esri/symbols/TextSymbol",
"esri/symbols/Font",
"esri/Color",
"esri/layers/FeatureLayer",
"esri/renderers/SimpleRenderer",
"dojo/domReady!"
], function(
Map, TextSymbol, Font,
Color, FeatureLayer, SimpleRenderer
) {
var map = new Map("map-div", {
center: [-122.445, 37.752],
zoom: 14,
basemap: "gray"
});
var treeColor = new Color("#666");
var treesUrl = "http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Street_Trees/FeatureServer/0";
var font = new Font("20pt", Font.STYLE_NORMAL,
Font.VARIANT_NORMAL, Font.WEIGHT_BOLD,"FontAwesome");
// you can use the cheatseeht to copy paste the font symbol
// http://fortawesome.github.io/Font-Awesome/cheatsheet/
var sym = new TextSymbol("", font, treeColor);
var renderer = new SimpleRenderer(sym);
var fl = new FeatureLayer(treesUrl);
fl.setRenderer(renderer);
map.addLayer(fl);
}); You'll get the same result as above, but with less code. You can find an example of this here. Why? Are you asking yourself why bother with this? Why not just use PictureMarkerSymbol and be done with it? I'll tell you why. Fonts scale, pictures don't. Have you ever loaded a PictureMarkerSymbol and had some jagged edges or maybe it was a little blurry? Especially if you tried redefining the size to fit better with your map? Fonts, like SVG vector graphics, scale so that if they are displayed at 8pt or 50pt, they don't pixelate and that is well enough reason for me to use them. This works pretty well and looks good for mobile apps. Granted, the font icon can't be multiple colors or very complicated, but look over the icons alone in Font Awesome or better yet the Mapbox maki icon set and you'll see there is lots of good stuff you may be able to use as a marker on your map. Check out my regular blog for more geodev tips & tricks! Go forth and hack away folks!
... View more
01-07-2015
07:30 AM
|
6
|
2
|
4682
|
|
POST
|
If you are using 3.10, you'll need to hack it a little bit using setRequestPreCallback as described in this thread.
... View more
12-31-2014
10:05 AM
|
0
|
1
|
2799
|
|
BLOG
|
So you made a badass webmap. Your webmap is kicking butt and taking names. You've got some nice looking custom tools maybe. Maybe you built a custom search tool or a nice looking display of your attribute data. But you start to think, hmm, I'd like to give my whole application a theme. Maybe it's focused on some water resources or does some sort of forest density analysis. But one thing looks the same across all your maps... your zoom slider. Hmm. It doesn't look bad, but it could look better. The CSS classes There are a few things you could do to customize the slider pretty easily using CSS. It doesn't take a whole lot of work, but it could add that little bit of flair to your application. So here is a list of the classes associated with the slider that will come in handy. .esriSimpleSlider .esriSimpleSlider div .esriSimpleSliderVertical .esriSimpleSliderIncrementButton .esriSimpleSliderVertical .esriSimpleSliderDecrementButton .esriSimpleSliderHorizontal .esriSimpleSliderIncrementButton .esriSimpleSliderHorizontal .esriSimpleSliderDecrementButton .esriSimpleSliderDecrementButton:hover,.esriSimpleSliderIncrementButton:hover .esriSimpleSliderDecrementButton:active,.esriSimpleSliderIncrementButton:active .esriSimpleSliderDisabledButton,.esriSimpleSliderDisabledButton:active,.esriSimpleSliderDisabledButton:hover That may seem like a big list, but you don't need to modify all of them, this is just what is described in the default css of the ArcGIS JS API. There are even more that have to do with the offsets based on the location of the slider on the page. You can start off playing around with the CSS in browser dev tools, like Chrome Dev Tools. This is an easy way to experiment with your application. Play around So a couple of neat things you can do is add a box shadow, remove the border and increase the size of the buttons for fat fingers on a mobile device. .esriSimpleSlider {
border: 0 solid #57585A;
/*shadow*/
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.12), 5px 5px 5px rgba(0, 0, 0, 0.12);
}
.esriSimpleSlider div {
width: 50px;
height: 50px;
line-height: 50px;
} This ends up looking like this. **Tip: If you change the button size, change the line-height to keep +/- centered. Not a huge difference, pretty subtle, but sets your application apart from others. You can see this demo here. Or maybe you want to update the color to match an overall theme of your application. You can adjust the CSS like this. .esriSimpleSlider {
border: 0 solid #57585A;
background-color: #02a7f8;
color: #FFF;
}
.esriSimpleSlider div {
width: 50px;
height: 50px;
line-height: 50px;
}
.esriSimpleSliderVertical .esriSimpleSliderIncrementButton {
border-bottom: 0 solid #57585A; /*setting to 0 removes the separator*/
} This ends up looking like this. **Tip: Note how I set the border to 0 to remove the separator between the buttons. You may want to do something like this if your application is embedded in another application and you want to make the user experience more seamless. You can see this demo here. Move it around Don't forget that the map constructor also has options to move the slider around. You can use sliderOrientation & sliderPosition to change the slider to suit your needs. Put it in the bottom-left corner or upper-right and horizontal. Play around with it. You can see a small demo here. So play around with some CSS and add a little flair to some of the lesser touched areas of your mapping application. This can help you build an overall theme to your map and app that set it aside just a bit.
... View more
12-31-2014
09:34 AM
|
2
|
0
|
1405
|
|
POST
|
This works for polygons, haven't tried with lines though. You can set the renderer to display markers. JS Bin - Collaborative JavaScript Debugging var layer = new FeatureLayer("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/5", {
outFields: ["*"],
infoTemplate: new InfoTemplate("${STATE_NAME}")
});
var markerSym = new SimpleMarkerSymbol();
markerSym.setColor(new Color("#78B378"));
markerSym.setOutline(markerSym.outline.setColor(new Color([133,197,133,0.75])));
var renderer1 = new SimpleRenderer(markerSym);
layer.setRenderer(ren
... View more
12-25-2014
11:01 AM
|
0
|
2
|
1264
|
|
BLOG
|
Also the arguments in dojo/lodash/jquery for iterators are not in ideal order for composition. So you can't do this. var sqrMap = libraryOfChoice.map(function(x) { return x*x; }); sqrMap([1,2,3,4]); But that's beside the point. If I were to use a third-party utility for arrays and overall functionality, I'd go with Ramda. or a combo of Ramda & lodash modules since you can load custom lodash builds.
... View more
12-24-2014
09:04 AM
|
0
|
0
|
1678
|
|
BLOG
|
Reverse while loops are sometimes the fastest overall, it all depends on the browser. On a side note, lo-dash has been part of the dojo foundation for a couple of years. Sizzle - The Dojo Foundation I don't know if that means we'll see some lo-dash in the future of dojo, but that would be interesting.
... View more
12-24-2014
08:47 AM
|
0
|
0
|
1678
|
|
BLOG
|
A long time ago, when web browsers were powered by gremlins and gnomes, we used to have to use JavaScript frameworks for the simplest of tasks. The most essential methods of objects such as the Array were in their infancy. You used to have to write loops manually, such as this: for (var i = 0; i < myArray.length; i++) {
// do something
} The horror. Then JavaScript developers were give a gift. The gift of iteration methods, such as map, filter, some and more. This greatly simplified how we could write code... unless you had to support Internet Explorer 8 and below. But before there was even an Internet Explorer 8, libraries like Dojo provided utilities to mimic these functions before they were finalized. This is where dojo/_base/array provided magical methods when we had to support browsers like Internet Explorer 6. Times were looking brighter. That was a long time ago. Browsers have come a long way. In my experience, even in government infrastructures, Internet Explorer 9 has become the minimum requirement I need to worry about. Dojo 2.0 is on the horizon (somewhere) and even in their own docs for dojo/_base/array it is stated: In Dojo 2.0, this module will likely be replaced with a shim to support functions on legacy browsers that don’t have these native capabilities. Emphasis is my own. What does that mean? That means you should stop using dojo/_base/array. That's how I'm reading it and I'm sticking to it. Do you still need to support Internet Explorer 8 and below? Use a shim/polyfill. Start writing your iterations like this: // get the attributes of all features
var onlyAttributes = features.map(function(feature) {
return f.attributes;
});
// find features with acreage greater than 500
var myFeatures = features.filter(function(feature) {
return feature.attributes.ACRES > 500;
});
// add graphics to the map
features.forEach(function(feature) {
this.map.graphics.add(feature);
}.bind(this)); // bind() is how you can pass context to functions
// find features with greater than 500 acres and get only the attributes
var myAttributes = features.filter(function(feature) {
return feature.attributes.ACRES > 500;
}).map(function(feature) {
return feature.attributes;
});
// get the first result of an address search
var address = addressCandidates.map(function(result) {
return result.address;
}).shift(); We should be incredibly grateful for dojo/_base/array and what it brought us as JavaScript developers in our time of need. But I'm pretty confident that time is behind us. When should I use dojo/_base/array? Ok, so there is a case when dojo/_base/array would be the only way to iterate an array, actually array-like objects, like arguments. For example: var func1 = function() {
arrayUtils.forEach(arguments, function(arg) {
console.debug(arg);
});
};
func1(1,2,3,4); //-> 1,2,3,4
var func2 = function() {
arguments.forEach(function(arg) {
console.debug(arg);
});
};
func2(1,2,3,4); //-> throws error This happens because although arguments is an array-like object that contains the arguments passed to a function, it doesn't have all the sugar a true Array has. But let's be honest here, were you really doing this? Probably not. It's typically best to avoid this behavior if you can. But if you really needed to, there is an easy way to do this. var func3 = function() {
[].forEach.call(arguments, function(arg) {
console.debug(arg);
});
}; Magic! To summarize: Use a polyfill if you want to play it safe. Use native Array iteration methods
... View more
12-24-2014
07:03 AM
|
1
|
8
|
3488
|
|
POST
|
I'm using Chrome DevTools and placed breakpoints at those three lines I mentioned.
... View more
12-23-2014
01:05 PM
|
0
|
1
|
2176
|
|
POST
|
That's odd. It could be timing issue. You could try moving the require() statement inside the the jQuery(document).ready(function($) {}) method, still setting define.amd.jQuery = false; If I step through with breakpoints at the jQuery(document), $("#selectProvinceListShortcode") and require() and wait a sec between each breakpoint, your map and page load without errror, so I'm thinking that means the timing is off with those. Actually, it worked without even setting the define.amd.jQuery = false, so you could probably remove that if it works in the ready method. I would probably go a step further and move all your jQuery stuff inside the the require method, don't even worry about jQuery(document) as the dojo/domReady! module does the same thing.
... View more
12-23-2014
12:38 PM
|
1
|
3
|
2176
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 3 weeks ago | |
| 2 | 2 weeks ago | |
| 2 | 05-19-2026 02:12 PM | |
| 1 | 04-24-2026 11:01 AM | |
| 2 | 04-21-2026 07:06 AM |
| Online Status |
Offline
|
| Date Last Visited |
yesterday
|