<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>Gavin Rehkemper</title><link>https://gavinr.com/</link><description>Recent content on Gavin Rehkemper</description><language>en</language><lastBuildDate>Sat, 01 Mar 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://gavinr.com/index.xml" rel="self" type="application/rss+xml"/><item><title>USA Counties</title><link>https://gavinr.com/usa-counties/</link><pubDate>Mon, 01 Apr 2024 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/usa-counties/</guid><description>&lt;p>There are 3,142 counties in the United States of America.&lt;/p>
&lt;h2 id="county-name-frequencies">County Name Frequencies&lt;/h2>
&lt;p>The most popular names for counties are past US presidents and founding fathers. 31 states have a &amp;ldquo;Washington&amp;rdquo; county, 26 states have a &amp;ldquo;Jefferson&amp;rdquo; county, and 24 four states have Franklin, Jackson, and Lincoln counties. Here is the full list:&lt;/p>
&lt;script src="https://gist.github.com/gavinr/7da2fbcf91c4065934f20f9a54c42cd4.js">&lt;/script>
&lt;style>.gist {max-height: 400px; overflow: scroll; overflow-x: scroll; margin-bottom: 10px;} .gist .blob-interaction-bar{display: none;} .blob-num.js-line-number {display: none;}&lt;/style>
&lt;p>And here&amp;rsquo;s an interactive map showing the location of those popular county names:&lt;/p>
&lt;iframe src="https://counties-viewer.gavinr.com/top-counties-by-state-map.html" style="width:100%; height: 400px;">&lt;/iframe>
&lt;div style="text-align: right; font-size: small;">&lt;a href="https://counties-viewer.gavinr.com/top-counties-by-state-map.html" target="_blank">Expand&lt;div style="transform: rotate(90deg);display: inline-block;margin-left: 5px;">⇱&lt;/div>&lt;/a>&lt;/div>
&lt;h2 id="most-unique-and-most-shared-county-names">Most Unique and Most Shared County Names&lt;/h2>
&lt;p>Here are the counties that have unique names - where there is not a single other county with the same name:&lt;/p>
&lt;iframe src="https://counties-viewer.gavinr.com/unique-counties.html" style="width:100%; height: 400px;">&lt;/iframe>
&lt;div style="text-align: right; font-size: small;">&lt;a href="https://counties-viewer.gavinr.com/unique-counties.html" target="_blank">Expand&lt;div style="transform: rotate(90deg);display: inline-block;margin-left: 5px;">⇱&lt;/div>&lt;/a>&lt;/div>
&lt;p>And here are the counties that have duplicates. In other words, the inverse of the above. Click on a county to see the other states with that county:&lt;/p>
&lt;iframe src="https://counties-viewer.gavinr.com/duplicate-counties.html" style="width:100%; height: 400px;">&lt;/iframe>
&lt;div style="text-align: right; font-size: small;">&lt;a href="https://counties-viewer.gavinr.com/duplicate-counties.html" target="_blank">Expand&lt;div style="transform: rotate(90deg);display: inline-block;margin-left: 5px;">⇱&lt;/div>&lt;/a>&lt;/div>
&lt;p>And here&amp;rsquo;s a map of the duplicate counties that have only one duplicate - &amp;ldquo;sister counties&amp;rdquo; if you will:&lt;/p>
&lt;iframe src="https://counties-viewer.gavinr.com/duplicate-counties.html?num=2" style="width:100%; height: 400px;">&lt;/iframe>
&lt;div style="text-align: right; font-size: small;">&lt;a href="https://counties-viewer.gavinr.com/duplicate-counties.html?num=2" target="_blank">Expand&lt;div style="transform: rotate(90deg);display: inline-block;margin-left: 5px;">⇱&lt;/div>&lt;/a>&lt;/div>
&lt;h2 id="county-size">County Size&lt;/h2>
&lt;p>The largest counties are in Alaska. The largest county in the continental US is San Bernadino county in California. The smallest county is Falls Church county in Virginia, just east of Washington DC.&lt;/p>
&lt;iframe src="https://counties-viewer.gavinr.com/county-size.html" style="width:100%; height: 400px;">&lt;/iframe>
&lt;div style="text-align: right; font-size: small;">&lt;a href="https://counties-viewer.gavinr.com/county-size.html" target="_blank">Expand&lt;div style="transform: rotate(90deg);display: inline-block;margin-left: 5px;">⇱&lt;/div>&lt;/a>&lt;/div>
&lt;h2 id="city-county-names">City-County Names&lt;/h2>
&lt;p>Some counties are named for the largest city within them. Here&amp;rsquo;s a map of the largest cities in the USA. Green circles indicate that the county shares its name with the city. Zoom in to see the details:&lt;/p>
&lt;iframe src="https://counties-viewer.gavinr.com/city-county-same-name.html" style="width:100%; height: 400px;">&lt;/iframe>
&lt;div style="text-align: right; font-size: small;">&lt;a href="https://counties-viewer.gavinr.com/city-county-same-name.html" target="_blank">Expand&lt;div style="transform: rotate(90deg);display: inline-block;margin-left: 5px;">⇱&lt;/div>&lt;/a>&lt;/div></description></item><item><title>Joplin Bulletify</title><link>https://gavinr.com/joplin-bulletify/</link><pubDate>Thu, 14 Mar 2024 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/joplin-bulletify/</guid><description>&lt;p>&lt;a href="https://joplinapp.org/">Joplin&lt;/a> is note-taking software that I appreciate and use a lot.
I use it to take all kinds of notes at home and work.&lt;/p>
&lt;p>I have one specific workflow where I copy/paste some lines of text into a
Joplin note, and I need to make all the lines (that are not headers) into bulleted lines.
The default bullet tool doesn&amp;rsquo;t work because it makes anything that is highlighted into bullets.
So I created a custom Joplin plugin called &amp;ldquo;Joplin Bulletify&amp;rdquo;.
It&amp;rsquo;s a very simple plugin - it adds a button to the toolbar.
When that button is clicked, the plugin adds a bullet to any line that is not already a header.
That&amp;rsquo;s it.&lt;/p>
&lt;p>&lt;video
autoplay="true" muted
loop="true"
width="100%"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/joplin-bulletify.mp4" type="video/mp4" />
&lt;/video>&lt;/p>
&lt;p>If you&amp;rsquo;d like to use it, go to &lt;code>Joplin Options &amp;gt; Plugins&lt;/code> and search for &lt;code>Bulletify&lt;/code>.&lt;/p>
&lt;p>&lt;img src="https://gavinr.com/posts/images/joplin-bulletify-options.png" alt="Joplin Bulletify in the Joplin Options" title="Joplin Bulletify in the Joplin Options">&lt;/p>
&lt;p>Since this is a modern Joplin plugin, for the plugin to work you must also go into Joplin&amp;rsquo;s &lt;code>General&lt;/code> Options and check on &lt;code>Opt-in to the Editor Beta&lt;/code>. In the future once the new Editor becomes the default this extra step will not be required.&lt;/p></description></item><item><title>Map Your Luck</title><link>https://gavinr.com/map-your-luck/</link><pubDate>Fri, 09 Jun 2023 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/map-your-luck/</guid><description>&lt;p>Just for fun, I thought it might be interesting to bring some of the ideas of the old game show &lt;em>Press your Luck&lt;/em>&lt;/p>
&lt;p>&lt;a href="https://www.youtube.com/watch?v=Cx92t-YdeQA">&lt;p>&lt;video
autoplay="true" muted
loop="true"
width="100%"
>
&lt;source src="https://gavinr.com/posts/videos/press-your-luck.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;p>&amp;hellip; over into an interactive web map:&lt;/p>
&lt;p>&lt;a href="https://map-your-luck.gavinr.com/">&lt;p>&lt;video
autoplay="true" muted
loop="true"
width="100%"
>
&lt;source src="https://gavinr.com/posts/videos/map-your-luck.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;p>There is no &amp;ldquo;whammy&amp;rdquo; in mine - it&amp;rsquo;s more of just a random item chooser.&lt;/p>
&lt;p>From the homepage you can select which &amp;ldquo;type&amp;rdquo; of geography you want to use (world countries, USA states, etc.) or you use your own layer by passing in any URL to an ArcGIS Feature Service.
Just include your URL in the URL in this format:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&amp;lt;https://map-your-luck.gavinr.com/map.html?layer&lt;span style="color:#f92672">=&lt;/span>your_url&amp;gt;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;style type="text/css">
.highlight {font-size:12px;}
&lt;/style>
&lt;p>Have fun!&lt;/p>
&lt;p style="text-align: center;">&lt;a href="https://map-your-luck.gavinr.com">&lt;strong>map-your-luck.gavinr.com&lt;/strong>&lt;/a>&lt;/p></description></item><item><title>Filter Tiled Layers</title><link>https://gavinr.com/geometry-filter-tiled-layers-arcgis-javascript/</link><pubDate>Thu, 08 Jun 2023 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/geometry-filter-tiled-layers-arcgis-javascript/</guid><description>&lt;p>One of the core ideas in mapping is the difference between vector and raster layers.
For vector layers, the actual geometry data is stored and passed around - for example a point might store the latitude and longitude.
For tiled raster layers, the data is stored as images on the server, and those images are displayed as the layer.&lt;/p>
&lt;p>In the past, the visualization of tiled raster layers could not be filtered based on geometry.
Using layer blending in recent versions of the ArcGIS Maps SDK for JavaScript, this is now possible.&lt;/p>
&lt;p>The documentation has a &lt;a href="https://developers.arcgis.com/javascript/latest/sample-code/layers-imagerytilelayer/">very flashy example&lt;/a> of a use case for blending, but what I&amp;rsquo;m talking about here is a bit simpler: visually filtering the tiled layer based on a vector layer.
For example, filtering your layer based on currently selected states:&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/RwJjBRN">&lt;p>&lt;video
autoplay="true" muted
loop="true"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/filter-states.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;p>This might seem basic, and for vector layers it is - we could do this kind of visual filtering for many years.
But for tiled layers this is new.&lt;/p>
&lt;p>You can get creative with this functionality. Like what if you allow the user to draw on the map to &amp;ldquo;cut out&amp;rdquo; their imagery visually:&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/KKBjGgE">&lt;p>&lt;video
autoplay="true" muted
loop="true"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/cut-via-draw.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;p>Or what if we hook this functionality up to a mouse hover:&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/full/BaGyrZW">&lt;p>&lt;video
autoplay="true" muted
loop="true"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/filter-tiled-layers-hover.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;p>Filtering tiled layers opens up more options for maps and geoviz web applications.
Give it a try next time you need to do some map filtering.&lt;/p></description></item><item><title>Using the WGS 84 Coordinate System in ArcGIS JavaScript Maps</title><link>https://gavinr.com/wgs84-4326-arcgis-maps-sdk-javascript/</link><pubDate>Wed, 22 Mar 2023 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/wgs84-4326-arcgis-maps-sdk-javascript/</guid><description>&lt;p>&lt;a href="https://en.wikipedia.org/wiki/Web_Mercator_projection">Web Mercator&lt;/a> is the standard for online interactive maps.
It has been the standard since Google Maps first used it in 2005.&lt;/p>
&lt;p>In the ArcGIS Maps SDK for JavaScript, Web Mercator basemaps are built-in and can be referenced &lt;a href="https://developers.arcgis.com/javascript/latest/api-reference/esri-Map.html#basemap">by name&lt;/a>.
The data for the built-in basemaps can be found in &lt;code>Basemap.js&lt;/code>.
Here&amp;rsquo;s a JavaScript demo showing that raw data:&lt;/p>
&lt;iframe height="500" style="width: 100%;margin-bottom: 40px;" scrolling="no" title="ArcGIS Maps SDK for JavaScript 4 - Basemap Data" src="https://codepen.io/gavinr/embed/WNgMeeM?height=265&amp;theme-id=light&amp;default-tab=result" frameborder="no" allowtransparency="true" allowfullscreen="true">
See the Pen &lt;a href='https://codepen.io/gavinr/pen/WNgMeeM'>ArcGIS Maps SDK for JavaScript 4 - Basemap Data&lt;/a> by Gavin Rehkemper
(&lt;a href='https://codepen.io/gavinr'>@gavinr&lt;/a>) on &lt;a href='https://codepen.io'>CodePen&lt;/a>.
&lt;/iframe>
&lt;p>And here are those basemaps in a Basemap Gallery:&lt;/p>
&lt;iframe height="500" style="width: 100%;margin-bottom: 40px;" scrolling="no" title="Basemap Gallery Expand" src="https://codepen.io/gavinr/embed/oJPraR?height=265&amp;theme-id=light&amp;default-tab=result" frameborder="no" allowtransparency="true" allowfullscreen="true" >
See the Pen &lt;a href='https://codepen.io/gavinr/pen/oJPraR'>Basemap Gallery Expand&lt;/a> by Gavin Rehkemper
(&lt;a href='https://codepen.io/gavinr'>@gavinr&lt;/a>) on &lt;a href='https://codepen.io'>CodePen&lt;/a>.
&lt;/iframe>
&lt;p>But what if we want to use the &lt;a href="https://en.wikipedia.org/wiki/World_Geodetic_System">EPSG 4326 spatial reference&lt;/a>, using latitude/longitude.
Basemaps in that spatial reference are not built-in to the SDK.&lt;/p>
&lt;p>We&amp;rsquo;ll first need some basemaps in that spatial reference.
Esri maintains &lt;a href="https://www.arcgis.com/home/group.html?id=4c790318395940c18a16e8acd721de25">an ArcGIS Online group&lt;/a> that contains EPSG 4326 (WGS 84) vector tile basemaps.
To create a Basemap instance in the SDK, all we need is the Web Map item ID.
So we&amp;rsquo;ll query the group, get the IDs, build the Basemap instances, and pass the array of Basemaps to the Basemap Gallery:&lt;/p>
&lt;iframe height="500" style="width: 100%;margin-bottom: 40px;" scrolling="no" title="WGS 84 Basemap Picker - ArcGIS Maps SDK for JavaScript" src="https://codepen.io/gavinr/embed/KKxRJoZ?height=265&amp;theme-id=light&amp;default-tab=result" frameborder="no" allowtransparency="true" allowfullscreen="true">
See the Pen &lt;a href='https://codepen.io/gavinr/pen/KKxRJoZ'>WGS 84 Basemap Picker - ArcGIS Maps SDK for JavaScript&lt;/a> by Gavin Rehkemper
(&lt;a href='https://codepen.io/gavinr'>@gavinr&lt;/a>) on &lt;a href='https://codepen.io'>CodePen&lt;/a>.
&lt;/iframe>
&lt;p>Can you see the difference between the two spatial references?
In EPSG 4326, the United States looks wider than when using Web Mercator.
Here&amp;rsquo;s an easier way to compare - swapping between the two:&lt;/p>
&lt;iframe height="500" style="width: 100%;margin-bottom: 40px;" scrolling="no" title="Swap EPSG 4326 (WGS 84) and Web Mercator Basemaps - ArcGIS Maps SDK for JavaScript" src="https://codepen.io/gavinr/embed/OJowXzj?height=265&amp;theme-id=light&amp;default-tab=result" frameborder="no" allowtransparency="true" allowfullscreen="true">
See the Pen &lt;a href='https://codepen.io/gavinr/pen/OJowXzj'>Swap EPSG 4326 (WGS 84) and Web Mercator Basemaps - ArcGIS Maps SDK for JavaScript&lt;/a> by Gavin Rehkemper
(&lt;a href='https://codepen.io/gavinr'>@gavinr&lt;/a>) on &lt;a href='https://codepen.io'>CodePen&lt;/a>.
&lt;/iframe>
&lt;p>&lt;strong>With great power comes great responsibility!&lt;/strong>&lt;/p>
&lt;p>Now that you know how to do it, should you?
Probably not.
Web Mercator is standard for interactive web mapping applications for many reasons.
It &lt;a href="https://www.youtube.com/watch?v=R-ENwz5u7pE">is not that great either&lt;/a>, but it&amp;rsquo;s the best we have for the web.&lt;/p>
&lt;p>Are you using EPSG 4326 (WGS 84) in your web apps? I&amp;rsquo;d &lt;a href="https://gavinr.com/contact">love to hear&lt;/a> about where you&amp;rsquo;ve found use for this pattern.&lt;/p></description></item><item><title>Clean Pull Request Diffs</title><link>https://gavinr.com/clean-pull-request-diffs/</link><pubDate>Sat, 31 Dec 2022 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/clean-pull-request-diffs/</guid><description>&lt;p>When collaborating on code with others using Git, keeping the overall list of code changes (the &amp;ldquo;diff&amp;rdquo;) in a pull request as small as possible - not including lots of unnecessary changes like quotes and tabbing - is an important and considerate thing to do.&lt;/p>
&lt;h2 id="why-lots-of-unrelated-changes-suck">Why lots of unrelated changes suck&lt;/h2>
&lt;p>A pull request (aka merge request) represents a request to merge a branch that has multiple outstanding commits, with each of those commits representing a variety of lines of code changes. These code changes are shown on the pull request summary and is one of the main things someone who reviews the pull request reviews.&lt;/p>
&lt;p>For those reviewers, it takes time and mental energy to understand what code change you&amp;rsquo;re proposing: what it intends to do, what it actually does, and if there are any obvious bugs.
When you have many un-related changed lines in the diff, that forces the reviewer to &lt;em>also&lt;/em> analyze which lines are &amp;ldquo;actual&amp;rdquo; changed lines and which are unnecessary and can be ignored.&lt;/p>
&lt;p>&lt;a href="https://gavinr.com/posts/images/dirty-diff.png">&lt;img src="https://gavinr.com/posts/images/dirty-diff.png" alt="Dirty diff" title="Dirty diff">&lt;/a>
&lt;em>A diff that&amp;rsquo;s hard to see what are the significant changes&lt;/em>&lt;/p>
&lt;h2 id="it-discourages-good-reviews">It discourages (good) reviews&lt;/h2>
&lt;p>The review process is already difficult enough.
In many situations the reviewer is taking time out of his/her busy schedule to change contexts and review your code.
Switching gears to a new project and then fully understanding the changes to the code takes a lot of effort, and adding any additional challenge to this process makes it that much harder.
If a reviewer sees a large PR with a bunch of unnecessary code changes, it may influence him or her to just skip the review or perform a &amp;ldquo;low value review.&amp;rdquo;&lt;/p>
&lt;h2 id="avoid-it">Avoid it&lt;/h2>
&lt;p>So, create change requests that contain only the minimum necessary code changes to fix the bug or add the feature that your pull request is trying to do.
Any additional lines are detrimental to the software creation process.&lt;/p></description></item><item><title>Georeference an Image with an Extent in ArcGIS Pro</title><link>https://gavinr.com/georeference-image-extent-arcgis-pro/</link><pubDate>Thu, 15 Dec 2022 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/georeference-image-extent-arcgis-pro/</guid><description>&lt;p>You can do a lot with rasters and imagery in ArcGIS Pro, the most basic of which is adding an image to a map.&lt;/p>
&lt;p>When adding an image to a map, if it does not have geographical metadata within the file, the image will be placed at (0, 0) - &lt;a href="https://en.wikipedia.org/wiki/Null_Island">Null Island&lt;/a>.&lt;/p>
&lt;p>&lt;img src="https://gavinr.com/posts/images/georeferenced-null-island.png" alt="Image georeferenced to Null Island" title="Image georeferenced to Null Island">&lt;/p>
&lt;p>To place the image at the correct location, you must tell ArcGIS Pro where on the map to place it. This is called Georeferencing.&lt;/p>
&lt;p>The way to georeference an image is to create &amp;ldquo;&lt;a href="https://pro.arcgis.com/en/pro-app/latest/help/data/imagery/georeferencing-tools.htm">Control points&lt;/a>,&amp;rdquo; which match the points on the image to points on the map.
If you do this at least 3 or 4 times, ArcGIS Pro can interpolate the rest of the image and get it to where it needs to go.&lt;/p>
&lt;p>What if you have an image and you know its &lt;strong>extent&lt;/strong> (that is, the coordinates of each of its sides - xmin, xmax, ymin, ymax)?
You should not need to create control points - you should be able to tell ArcGIS Pro &amp;ldquo;stretch this image between these 4 corners (the extent values)&amp;rdquo; and that&amp;rsquo;s all - no manual control points needed.&lt;/p>
&lt;p>The solution is to create a world file.
The world file is a six-line plain text file that is designed for this purpose⁠ — to georeference an image.
This is the template to convert the extent values to a world file:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-html" data-lang="html">&lt;span style="display:flex;">&lt;span>(XMAX-XMIN)/(IMAGE_WIDTH)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-(YMAX-YMIN/(IMAGE_HEIGHT))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>XMIN
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>YMAX&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;p>The convention is to name the world file the same file extension but with a &amp;ldquo;w&amp;rdquo; appended. So if you have a PNG, create a file with the same name as the image, but file extension &amp;ldquo;.pngw&amp;rdquo; instead of &amp;ldquo;.png&amp;rdquo;. Save this in the same directory as the image, then re-add the image to a map in ArcGIS Pro. Your image will be placed in the exactly correct spot!&lt;/p>
&lt;p>&lt;img src="https://gavinr.com/posts/images/georeferenced.png" alt="Image georeferenced to Null Island" title="Image georeferenced to Null Island">&lt;/p></description></item><item><title>The Elusive Draggable Map Popup</title><link>https://gavinr.com/draggable-popup-arcgis-javascript/</link><pubDate>Thu, 23 Jun 2022 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/draggable-popup-arcgis-javascript/</guid><description>&lt;p>In the &lt;a href="https://developers.arcgis.com/javascript/">ArcGIS Maps SDK for JavaScript&lt;/a>, the popup widget displays the attributes for individual features on the map.
It appears when the user clicks on a feature on the map.&lt;/p>
&lt;p>&lt;img src="https://gavinr.com/posts/images/popup-js-api-4.png" alt="Map of the USA with a popup on Sterling, CO" title="The map popup in all its glory">&lt;/p>
&lt;p>In certain cases, you may want the user to be able to move the popup by dragging the mouse cursor. But there&amp;rsquo;s no way to enable that in the API!&lt;/p>
&lt;p>Allowing the user to move the popup is not common and probably not best practice in most cases.
The popup displays attributes about a feature, and the alignment of the popup near the feature tells the user the which feature&amp;rsquo;s attributes the popup is showing.&lt;/p>
&lt;p>You might want to allow the user to move the popup because it &amp;ldquo;gets in the way&amp;rdquo;. This is usually not actually a problem because:&lt;/p>
&lt;ol>
&lt;li>It&amp;rsquo;s quite easy to close the popup by clicking on the close button or clicking anywhere on the map, and&lt;/li>
&lt;li>There&amp;rsquo;s the &lt;a href="https://developers.arcgis.com/javascript/latest/sample-code/popup-docking-position/">&amp;ldquo;docking&amp;rdquo; option&lt;/a> which places the popup in one of the corners of the map.&lt;/li>
&lt;/ol>
&lt;p>If your use case overrides all of those considerations and you do want to allow dragging, here is a sample using the &lt;a href="https://interactjs.io/">Interact.js JavaScript library&lt;/a>.
Since the popup DOM node is created each time the popup opens, it sets up and destroys the Interact.js listeners when the popup opens and closes using the &lt;code>watch&lt;/code> functionality of the ArcGIS Maps SDK for JavaScript.
Other than that, the code is straightforward Interact.js.
Click here for the full code and interactive sample:&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/PoQvXxo?editors=0010">&lt;p>&lt;video
autoplay="true" muted
loop="true"
width="100%"
>
&lt;source src="https://gavinr.com/posts/videos/draggable-popup.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;p style="text-align: center;">&lt;a href="https://codepen.io/gavinr/pen/PoQvXxo?editors=0010">View the sample&lt;/a>&lt;/p>
&lt;p>In what type of mapping applications have you used draggable popups? &lt;a href="https://gavinr.com/contact">Let me know&lt;/a>.&lt;/p></description></item><item><title>Query All Features from a Feature Service</title><link>https://gavinr.com/query-all-features-from-feature-service/</link><pubDate>Tue, 31 May 2022 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/query-all-features-from-feature-service/</guid><description>&lt;p>When querying an ArcGIS Feature Service, there is typically a maximum number of features (records) that will be returned from any query – usually set to 1000. If you want to query for &lt;strong>all&lt;/strong> the features in the service, ArcGIS REST JS does not currently do this (see &lt;a href="https://github.com/Esri/arcgis-rest-js/issues/690">this discussion&lt;/a>) - you’ll need to make multiple REST calls to get them all. Use the package &lt;a href="https://www.npmjs.com/package/query-all-features">query-all-features&lt;/a> to do this.&lt;/p>
&lt;p>First install the package:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>npm install query-all-features
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then use it in your code. It takes as input the same object as the &lt;a href="https://developers.arcgis.com/arcgis-rest-js/api-reference/arcgis-rest-feature-service/queryFeatures">queryFeatures endpoint of ArcGIS REST JS&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-js" data-lang="js">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">queryAllFeatures&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#34;query-all-features&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">queryAllFeatures&lt;/span>({
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">url&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/0&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}).&lt;span style="color:#a6e22e">then&lt;/span>((&lt;span style="color:#a6e22e">results&lt;/span>) =&amp;gt; {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;results&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">results&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}, (&lt;span style="color:#a6e22e">err&lt;/span>) =&amp;gt; {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">error&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;err&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>});
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can also use it in &lt;a href="https://github.com/gavinr/query-all-features#node-js">NodeJS&lt;/a>, in the &lt;a href="https://github.com/gavinr/query-all-features#browser---es-modules-via-cdn">browser via ES Modules (via CDN)&lt;/a>, and in the &lt;a href="https://github.com/gavinr/query-all-features#browser---script-tag-via-umd-cdn">browser via a script tag&lt;/a>. Here&amp;rsquo;s a full code sample in action:&lt;/p>
&lt;iframe height="500" style="width: 100%;" scrolling="no" title="Query all features from a feature service - ArcGIS REST JS" src="https://codepen.io/gavinr/embed/ExQYegd?height=265&amp;theme-id=light&amp;default-tab=result" frameborder="no" allowtransparency="true" allowfullscreen="true">
See the Pen &lt;a href='https://codepen.io/gavinr/pen/ExQYegd'>Query all features from a feature service - ArcGIS REST JS&lt;/a> by Gavin Rehkemper
(&lt;a href='https://codepen.io/gavinr'>@gavinr&lt;/a>) on &lt;a href='https://codepen.io'>CodePen&lt;/a>.
&lt;/iframe>
&lt;p>More information is on GitHub: &lt;a href="https://github.com/gavinr/query-all-features">&lt;strong>github.com/gavinr/query-all-features&lt;/strong>&lt;/a>&lt;/p></description></item><item><title>Import Mapping Libraries from a URL</title><link>https://gavinr.com/arcgis-js-api-es-modules-cdn-url/</link><pubDate>Mon, 07 Mar 2022 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/arcgis-js-api-es-modules-cdn-url/</guid><description>&lt;p>When adding functionality to a web page using JavaScript, you may rely on external libraries (like a mapping library) to provide that functionality so you do not need to write it yourself. There are many ways to use, or import, these libraries into the page. A new method is to use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules">ES Modules&lt;/a> to import third-party JavaScript libraries into your application &lt;em>from a URL&lt;/em>. Using this method is easier because downloading or installing via NPM is not necessary.&lt;/p>
&lt;p>For mapping applications with the &lt;a href="https://js.arcgis.com">ArcGIS Maps SDK for JavaScript&lt;/a>, I&amp;rsquo;ve found that using this &amp;ldquo;ES Modules via CDN URL&amp;rdquo; pattern is great for quick samples or debugging. This pattern should not be used for production code - see notes in the documentation &lt;a href="https://developers.arcgis.com/javascript/latest/es-modules/#using-the-esm-cdn">here&lt;/a>.&lt;/p>
&lt;p>To use this pattern, the key is to add &lt;code>type=&amp;quot;module&amp;quot;&lt;/code> to your &lt;code>&amp;lt;script&amp;gt;&lt;/code> tag. For the ArcGIS Maps SDK for JavaScript, the URL pattern is to take whatever import string is shown in the API documentation (for example, &lt;code>@arcgis/core/views/MapView&lt;/code>), and:&lt;/p>
&lt;ol>
&lt;li>&lt;em>prepend&lt;/em> &lt;code>https://js.arcgis.com/X.XX/&lt;/code> (where &lt;code>X.XX&lt;/code> is the version number, like &lt;code>4.22&lt;/code>), and&lt;/li>
&lt;li>&lt;em>append&lt;/em> &lt;code>.js&lt;/code> to the end.&lt;/li>
&lt;/ol>
&lt;p>So if you want a plain HTML and JavaScript file solution, it would look like &lt;a href="https://github.com/Esri/jsapi-resources/blob/04f8892073210c132fabde4f44035d3b2f5acda9/esm-samples/jsapi-esm-cdn/esm-cdn.html">this&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-html" data-lang="html">&lt;span style="display:flex;">&lt;span>&amp;lt;&lt;span style="color:#f92672">script&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;module&amp;#34;&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> import MapView from &amp;#39;https://js.arcgis.com/4.22/@arcgis/core/views/MapView.js&amp;#39;;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>When using code-sharing websites like CodePen, you do not have control over the &lt;code>&amp;lt;script&amp;gt;&lt;/code> tag, so you might think using this pattern will not work. Luckily, these websites have embraced ES Modules and have a solution.&lt;/p>
&lt;h3 id="codepen">CodePen&lt;/h3>
&lt;p>CodePen will automatically add the &lt;code>type=&amp;quot;module&amp;quot;&lt;/code> tag to your &lt;code>&amp;lt;script&amp;gt;&lt;/code> tag if it detects that you&amp;rsquo;re using ES Modules. Details on that &lt;a href="https://blog.codepen.io/documentation/es-modules-on-codepen/">here&lt;/a>.&lt;/p>
&lt;p>&lt;a href="https://codepen.io/pen?template=vYypeKL&amp;amp;editors=0010">CodePen - ArcGIS JS API - ES Modules Template&lt;/a>&lt;/p>
&lt;h3 id="codesandbox">CodeSandbox&lt;/h3>
&lt;p>In CodeSandbox, if you use the &amp;ldquo;esm-react&amp;rdquo; environment you can use ES Modules.&lt;/p>
&lt;p>&lt;a href="https://codesandbox.io/s/arcgis-js-api-esm-and-react-via-cdn-template-t3v0fr?file=/src/EsriMap.jsx">CodeSandbox - ArcGIS JS API - ES Modules Template&lt;/a>&lt;/p>
&lt;h3 id="leaflet-and-esri-leaflet">Leaflet and Esri Leaflet&lt;/h3>
&lt;p>For libraries like &lt;a href="https://leafletjs.com/">Leaflet&lt;/a> or &lt;a href="https://github.com/Esri/esri-leaflet">Esri Leaflet&lt;/a> where ES Module builds are not provided (yet), you can use the &lt;a href="https://www.skypack.dev/">Skypack CDN&lt;/a> like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-js" data-lang="js">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">as&lt;/span> &lt;span style="color:#a6e22e">L&lt;/span> &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#34;https://cdn.skypack.dev/leaflet@1.7.1&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">as&lt;/span> &lt;span style="color:#a6e22e">esriLeaflet&lt;/span> &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#34;https://cdn.skypack.dev/esri-leaflet@3&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">as&lt;/span> &lt;span style="color:#a6e22e">esriLeafletVector&lt;/span> &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#34;https://cdn.skypack.dev/esri-leaflet-vector@3&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;a href="https://codepen.io/pen?template=wvoKwEv&amp;amp;editors=0010">CodePen - Esri Leaflet - ES Modules Template&lt;/a>&lt;/p></description></item><item><title>Yearly Checklist</title><link>https://gavinr.com/yearly-checklist-backup-privacy/</link><pubDate>Mon, 03 Jan 2022 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/yearly-checklist-backup-privacy/</guid><description>&lt;p>Happy new year! It&amp;rsquo;s a great time to complete those yearly things that are easily forgotten during the rest of the year: backups, privcy opt-outs, and software updates.&lt;/p>
&lt;h2 id="backups">Backups&lt;/h2>
&lt;p>If you don&amp;rsquo;t already have a daily backup system for your regularly-used files, set that up! &lt;a href="https://secure.backblaze.com/r/02wlml">Backblaze&lt;/a> or &lt;a href="https://spideroak.com/one/">SpiderOak&lt;/a> are great options. If you already have this set up, now is a great time to make sure it&amp;rsquo;s working properly and that you could access your files if your computer died.&lt;/p>
&lt;p>If the service that hosts your email or contacts goes down, how would you access that data? You couldn&amp;rsquo;t! So next, focus on data that is not stored on your computer. The list of places you should back up will be unique for each person, but here are some common places:&lt;/p>
&lt;ol>
&lt;li>GMail, Google Contacts, YouTube, etc. - you can download your data from any Google service pretty easily from &lt;a href="https://takeout.google.com">Google Takeout&lt;/a>.&lt;/li>
&lt;li>Email&lt;/li>
&lt;li>Password manager&lt;/li>
&lt;li>Calendar&lt;/li>
&lt;li>Contacts&lt;/li>
&lt;li>&lt;a href="https://github.com/karlicoss/rexport">Reddit submissions/comments/upvotes&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://meta.stackexchange.com/questions/269804/dump-of-my-own-stack-exchange-content">StackExchange&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://twitter.com/settings/your_twitter_data">Twitter&lt;/a>&lt;/li>
&lt;/ol>
&lt;h2 id="privacy">Privacy&lt;/h2>
&lt;p>First go through sites like &lt;a href="https://simpleoptout.com/">Simple Opt Out&lt;/a> to update your privacy preferences for websites and services you use. If you use credit cards, don&amp;rsquo;t miss those opt-outs (&lt;a href="https://marketingreportoptout.visa.com/OPTOUT/request.do">Visa&lt;/a>/&lt;a href="https://www.mastercard.us/en-us/vision/corp-responsibility/commitment-to-privacy/privacy/data-analytics-opt-out.html">Mastercard&lt;/a>)&lt;/p>
&lt;p>Next, on your mobile phone, review app settings and disable any access (for example, location access) that an app does not reasonably need. (on iPhone: &lt;code>Settings &amp;gt; Privacy&lt;/code>)&lt;/p>
&lt;p>Finally, if you don&amp;rsquo;t yet use the &lt;a href="https://ublockorigin.com/">uBlock Origin browser extension&lt;/a>, install it. If you already have it installed, make sure it&amp;rsquo;s getting updated with the latest blocking lists (also do this for any similar blocking system like Pi Hole or DNS blocks).&lt;/p>
&lt;p>&lt;em>More: &lt;a href="https://gavinr.com/three-tips-to-reduce-personal-data-tracking/">Three Tips to Reduce Personal Data Tracking&lt;/a>&lt;/em>&lt;/p>
&lt;h2 id="software-updates">Software Updates&lt;/h2>
&lt;p>Make sure your Operating system (like Windows) has all security updates installed. Check your home router firmware and make sure you&amp;rsquo;re on the latest version. Bonus points if you check other IoT devices like cameras, etc.&lt;/p></description></item><item><title>Support Software Developers</title><link>https://gavinr.com/support-software-developers/</link><pubDate>Mon, 13 Sep 2021 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/support-software-developers/</guid><description>&lt;p>Support what you use and enjoy. This is true in all aspects of life, including software. Especially open source software.&lt;/p>
&lt;p>Here are a few simple ways to do that.&lt;/p>
&lt;h2 id="1-star-the-project-on-github-free">1. &amp;ldquo;Star&amp;rdquo; the project on GitHub (FREE)&lt;/h2>
&lt;p>Giving a project a &amp;ldquo;star&amp;rdquo; tells the developer that you appreciate their effort. It costs you nothing, but is quite encouraging to the developer when it appears in the feed.&lt;/p>
&lt;p>This encouragement is important because open source projects generally do not get any feedback when the software works well &amp;ndash; the developer only hears about problems and bugs.&lt;/p>
&lt;p>&lt;img src="https://gavinr.com/posts/images/github-star.gif" alt="Click the GitHub Star">&lt;/p>
&lt;h2 id="2-send-a-personal-thank-you-message-free">2. Send a personal thank you message (FREE)&lt;/h2>
&lt;p>Find the developer&amp;rsquo;s email address via GitHub or their personal website, and send a quick note of thanks and appreciation. It need not be long or complex. Taking a small amount of time out of your day to do this is very meaningful and really encourages the developer.&lt;/p>
&lt;p>This can be done using social media, but I encourage doing it via email because it&amp;rsquo;s more personal and feels more direct. If you&amp;rsquo;re big into social media, do via social media &lt;em>and&lt;/em> email!&lt;/p>
&lt;h2 id="3-send-money">3. Send money&lt;/h2>
&lt;p>If you have the means, taking a small portion of your donation budget each year to send it to software developers who work on the software you enjoy is a great way of saying thanks. Sending a donation is easier than ever.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>If the software has an Info or About page, it might mention ways to donate there.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If the project has a GitHub page, check the &amp;ldquo;Sponsor this project&amp;rdquo; section.
&lt;a href="https://gavinr.com/posts/images/mac-dev-playbook-sponsort.png">&lt;img src="https://gavinr.com/posts/images/mac-dev-playbook-sponsort.png" style=" width:70%; border: 1px solid gray;" alt="Sponsor section of GitHub repository page" />&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Find a contributor by going to the GitHub repository &amp;ldquo;Insights &amp;gt; Contributors&amp;rdquo; page and see if they have a GitHub Sponsors or other sponsorship link on their user page.
&lt;a href="https://gavinr.com/posts/images/github-find-contributor.png">&lt;img src="https://gavinr.com/posts/images/github-find-contributor.png" style=" width:70%; border: 1px solid gray;" alt="Find the contributor on the GitHub Contributors page" />&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Find their personal homepage to see if they accept donations via an alternative method.
&lt;a href="https://gavinr.com/posts/images/jeff-geerling-personal-site-donation.png">&lt;img src="https://gavinr.com/posts/images/jeff-geerling-personal-site-donation.png" style=" width:70%; border: 1px solid gray;" alt="Jeff Geerling website" />&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If none of these steps led you to a donation page, go back to option two above, and ask if they have a way to donate directly.&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>Quick Start Script for ArcGIS Experience Builder</title><link>https://gavinr.com/quick-start-script-arcgis-experience-builder/</link><pubDate>Wed, 04 Aug 2021 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/quick-start-script-arcgis-experience-builder/</guid><description>&lt;p>If you develop with ArcGIS Experience Builder, you know that getting started is a multi-step process. It would be nice to get started a little more quickly.&lt;/p>
&lt;p>Here&amp;rsquo;s a simple Windows batch script that will do that. It installs the dependencies, if necessary, and then starts up the Experience Builder server.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cmd" data-lang="cmd">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">exist&lt;/span> ArcGISExperienceBuilder/client/node_modules\ (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cmd /c start powershell -noexit -command &lt;span style="color:#e6db74">&amp;#34;cd ArcGISExperienceBuilder\client; npm start&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cmd /c start powershell -noexit -command &lt;span style="color:#e6db74">&amp;#34;cd ArcGISExperienceBuilder\server; npm start&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>) &lt;span style="color:#66d9ef">else&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cmd /c start powershell -noexit -command &lt;span style="color:#e6db74">&amp;#34;cd ArcGISExperienceBuilder\client; npm ci; npm start&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cmd /c start powershell -noexit -command &lt;span style="color:#e6db74">&amp;#34;cd ArcGISExperienceBuilder\server; npm ci; npm start&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">start&lt;/span> http://localhost:3000
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Usage:&lt;/p>
&lt;ol>
&lt;li>Download the Experience Builder developer edition zip file.&lt;/li>
&lt;li>Extract the Zip files. I use 7-zip and just use the &amp;ldquo;Extract here&amp;rdquo; button - this will create a folder called &lt;code>ArcGISExperienceBuilder&lt;/code> at the same level as the zip file.&lt;/li>
&lt;li>Create a file called &lt;code>LaunchExB.cmd&lt;/code>.&lt;/li>
&lt;li>Right-click the file and click &lt;code>Edit&lt;/code>. Copy/paste the code above.&lt;/li>
&lt;li>Double-click the file.&lt;/li>
&lt;/ol>
&lt;p>Note: make sure the &lt;code>.cmd&lt;/code> file you create is that the same level (siblings) as the &lt;code>ArcGISExperienceBuilder&lt;/code> folder.&lt;/p></description></item><item><title>SpongeBob Time Cards Generator</title><link>https://gavinr.com/spongebob-time-cards-generator-hours-later/</link><pubDate>Thu, 24 Jun 2021 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/spongebob-time-cards-generator-hours-later/</guid><description>&lt;p>You need a &lt;a href="https://spongebob.fandom.com/wiki/List_of_time_cards">SpongeBob time card&lt;/a> with your own text on it - what do you do?&lt;/p>
&lt;p>&lt;a href="https://spongebob.gavinr.com/">&lt;img src="https://gavinr.com/posts/images/spongebob-time-card-how.png" alt="alt text">&lt;/a>&lt;/p>
&lt;p>Use the &lt;a href="https://spongebob.gavinr.com/">&lt;strong>SpongeBob Time Cards Generator&lt;/strong>&lt;/a> of course!&lt;/p>
&lt;p>You can set your own message, choose from a variety of backgrounds, and change the text size. It even uses a SpongeBob style font!&lt;/p>
&lt;p>Check it out at &lt;a href="https://spongebob.gavinr.com">spongebob.gavinr.com&lt;/a>.&lt;/p></description></item><item><title>Automatic Wikipedia Links in ArcGIS Online Popups</title><link>https://gavinr.com/wikipedia-links-in-arcgis-online-popups/</link><pubDate>Fri, 28 May 2021 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/wikipedia-links-in-arcgis-online-popups/</guid><description>&lt;p>When adding a link to a popup in a map, using attribute-based URL parameters is a powerful ability. Bern Szukalski explains how to do this in this &lt;a href="https://www.esri.com/arcgis-blog/products/arcgis-online/mapping/url-parameters-pop-ups/">blog post&lt;/a>.&lt;/p>
&lt;p>He shows how to take the numeric ID from the a clicked feature (property parcel, in this case) and create a link with the ID so when the user clicks it will open the web page for that specific property ID.&lt;/p>
&lt;p>&lt;a href="https://www.esri.com/arcgis-blog/products/arcgis-online/mapping/url-parameters-pop-ups/">&lt;img src="https://gavinr.com/posts/images/attribute-based-link-popup-esri-blog.jpg" alt="alt text">&lt;/a>&lt;/p>
&lt;p>What if you don&amp;rsquo;t have IDs and a specific URL pattern, but instead want to pass the &lt;em>name&lt;/em> of your feature to enable the user to find some more information about it? You can use the same technique, using websites (like Google or Wikipedia) that take string searches as input.&lt;/p>
&lt;p>For example, you may have the names of US Forest Service Wilderness Areas as an attribute, and you want to have a link to each wilderness area&amp;rsquo;s Wikipedia Page. Follow the instructions in Bern&amp;rsquo;s blog post, and create a link tag (&lt;code>&amp;lt;a href=&amp;quot;...&lt;/code>) where the beginning of the URL is &lt;code>https://en.wikipedia.org/wiki/Special:Search/&lt;/code> then insert the dynamic value of the &amp;ldquo;name&amp;rdquo; attribute column of your features (for example, &lt;code>{my_name_field}&lt;/code>). So it will look something like this:&lt;/p>
&lt;p>&lt;img src="https://gavinr.com/posts/images/arcgis-online-poup-wikipedia.png" alt="Popup configuration panel in ArcGIS Online">&lt;/p>
&lt;p>This will create a clickable Wikipedia link in the popup that will open the proper page for each item.&lt;/p>
&lt;p>&lt;img src="https://gavinr.com/posts/images/wikipedia-link-in-popup.png" alt="Popup in map with Wikipedia link">&lt;/p>
&lt;p>See the result in the &lt;a href="https://arcgis.com/apps/instant/minimalist/index.html?appid=d81cadef79ce49b2b14094df7cede8b8">interactive map of the Wilderness Areas in Mark Twain National Forest&lt;/a>.&lt;/p>
&lt;h2 id="other-formats">Other Formats&lt;/h2>
&lt;p>You could do this with other URL formats too, like&lt;/p>
&lt;ol>
&lt;li>Google &amp;ldquo;Feeling Lucky&amp;rdquo; search (send the user to the first search result)
&lt;ul>
&lt;li>&lt;code>http://www.google.com/search?btnI&amp;amp;q={ATTRIBUTE_NAME}&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Flickr image search (show a list of related Flickr photos)
&lt;ul>
&lt;li>&lt;code>https://www.flickr.com/search/?text={ATTRIBUTE_NAME}&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>YouTube (send the user to the first video)
&lt;ul>
&lt;li>&lt;code>https://www.google.com/search?btnI&amp;amp;q=site:youtube.com {ATTRIBUTE_NAME}&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>C-SPAN Search (list of related C-SPAN articles and videos)
&lt;ul>
&lt;li>&lt;code>https://www.c-span.org/search/basic/?query={ATTRIBUTE_NAME}&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>With what other websites can you use this technique? &lt;a href="https://gavinr.com/contact">Let me know&lt;/a> and I&amp;rsquo;ll add them to the list!&lt;/p></description></item><item><title>Map Stream</title><link>https://gavinr.com/map-stream/</link><pubDate>Mon, 17 May 2021 03:15:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/map-stream/</guid><description>&lt;p>&lt;a href="https://map-stream.gavinr.com">&lt;img src="https://gavinr.com/posts/images/map-stream-live-stream-arcgis-online-maps.png" style="float:right; width:40%; " alt="map stream screenshot" />&lt;/a>
&lt;a href="https://map-stream.gavinr.com/">Map Stream&lt;/a> is a web app showing a live stream of newly-updated public maps on ArcGIS Online.&lt;/p>
&lt;p>The interesting thing about watching everything stream by is the variety: topic, location, age, popularity. Just about anything can pop up.&lt;/p>
&lt;p>Built with Svelte, the source code is public: &lt;a href="https://github.com/gavinr/map-stream">github.com/gavinr/map-stream&lt;/a>.&lt;/p>
&lt;p>Check it out: &lt;a href="https://map-stream.gavinr.com/">&lt;strong>map-stream.gavinr.com&lt;/strong>&lt;/a>&lt;/p></description></item><item><title>DigitalHealth Class</title><link>https://gavinr.com/digital-health-class/</link><pubDate>Thu, 11 Mar 2021 08:00:00 -0600</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/digital-health-class/</guid><description>&lt;p>When my friend Jake wakes up in the morning he immediately grabs his iPhone and checks Facebook. How common is that? Do you do it? Is waking up and checking Facebook healthy?&lt;/p>
&lt;p>What is the ideal relationship between humans and technology? We are still figuring that out, but some things are clear:&lt;/p>
&lt;ol>
&lt;li>Social media is the &amp;ldquo;junk food&amp;rdquo; of the internet.&lt;/li>
&lt;li>We must take steps to ensure the security of our data and our online privacy.&lt;/li>
&lt;li>The internet makes large-scale scams easier than ever before.&lt;/li>
&lt;/ol>
&lt;p>These are not widely known. Jake and his phone, social media addiction, and people getting fooled by internet scams are just some examples that show that a majority of Americans do not understand some of the basic tenets of a healthy digital life.&lt;/p>
&lt;h3 id="health-class">Health Class&lt;/h3>
&lt;p>Most US high schools require health class for graduation (&lt;a href="https://babel.hathitrust.org/cgi/pt?id=mdp.39015003811182&amp;amp;view=1up&amp;amp;seq=41">some history&lt;/a>). It teaches:&lt;/p>
&lt;ul>
&lt;li>Systems of the body&lt;/li>
&lt;li>Nutrition and fitness&lt;/li>
&lt;li>Safe use or avoidance of alcohol, tobacco, and drugs&lt;/li>
&lt;li>Reproductive health&lt;/li>
&lt;li>CPR and first aid&lt;/li>
&lt;/ul>
&lt;p>These are core, foundational topics that any future adult must know. In a society where everyone uses smartphones and is always on the internet, are technology health topics not equally important?&lt;/p>
&lt;h3 id="digitalhealth-class">DigitalHealth Class&lt;/h3>
&lt;p>I propose creating a new course, offered in parallel with the traditional health class. DigitalHealth Class wil teach basic skills and knowledge needed in a digital world. Basic modules would cover:&lt;/p>
&lt;ol>
&lt;li>Security
&lt;ol>
&lt;li>Basic tenets of online security (like how HTTPS/SSL works)&lt;/li>
&lt;li>Passwords and password managers&lt;/li>
&lt;li>Common scams (phishing, etc) and how to avoid them&lt;/li>
&lt;li>How to identify trustworthy websites&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>Privacy
&lt;ol>
&lt;li>Smart-phone settings (e.g. prevent location access)&lt;/li>
&lt;li>Browser settings (Cookies, etc)&lt;/li>
&lt;li>Ad blockers&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>Digital wellness
&lt;ol>
&lt;li>What aspects of the internet are &amp;ldquo;good for you&amp;rdquo;?&lt;/li>
&lt;li>Controlling your attention&lt;/li>
&lt;li>How and where do advertisers exert influence&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>Digital independence
&lt;ol>
&lt;li>Build your own website with HTML, CSS, and JavaScript&lt;/li>
&lt;li>Basic scripting (python)&lt;/li>
&lt;li>Data formats (txt, markdown, XML, RSS, etc)&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ol>
&lt;p>Since this is a new curriculum, most adults (especially those currently aged 50+) haven&amp;rsquo;t learned these valuable skills and lessons. So in addition to teaching this in high schools, this course could also be taught to a wider audience through libraries, senior centers, or even online.&lt;/p>
&lt;p>My friend Jake has recently started exercising regularly and is looking physically great and healthy. After taking DigitalHealth Class, hopefully he&amp;rsquo;ll start making equally healthy choices in his digital life.&lt;/p></description></item><item><title>Find Latitude/Longitude Coordinates in Two Clicks</title><link>https://gavinr.com/latitude-longitude-coordinate-finder/</link><pubDate>Thu, 11 Feb 2021 02:00:00 -0600</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/latitude-longitude-coordinate-finder/</guid><description>&lt;p>Finding the latitude and longitude coordinates of a particular location is not as easy as it should be. You can get it from Google Maps, but it requires 3 or 4 clicks. There are also a bunch of sites devoted to the task - most with ads and invasive spyware slowing down the page.&lt;/p>
&lt;p>We need something better - that&amp;rsquo;s why I created &lt;a href="https://latlonlocate.com/">Latitude Longitude Locate&lt;/a>. Latitude Longitude Locate is a simple mapping app designed for geo developers. Click on a location where you want to get the coordinates, and click the &amp;ldquo;copy&amp;rdquo; icon. Those coordinates are now on your clipboard - &lt;strong>two clicks&lt;/strong>.&lt;/p>
&lt;p>&lt;a href="https://latlonlocate.com">&lt;p>&lt;video
autoplay="true" muted
loop="true"
width="100%"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/latitude-longitude-locate.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;p>There are also a few more features, like the ability to swap the &lt;a href="https://macwright.com/lonlat/">order&lt;/a> of latitude/longitude.&lt;/p>
&lt;p>It&amp;rsquo;s meant to be simple and quick. I hope it helps you out. &lt;a href="https://gavinr.com/contact/">Let me know&lt;/a> if you have any ideas or suggestions to make it even better.&lt;/p>
&lt;p style="text-align: center;">&lt;strong>&lt;a href="https://latlonlocate.com">LatLonLocate.com&lt;/a>&lt;/strong>&lt;/p></description></item><item><title>Query to Get All Features in the ArcGIS Maps SDK for JavaScript</title><link>https://gavinr.com/arcgis-javascript-query-all-features/</link><pubDate>Wed, 28 Oct 2020 00:00:00 +0000</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/arcgis-javascript-query-all-features/</guid><description>&lt;p>When you&amp;rsquo;re querying a Feature Service in the ArcGIS Maps SDK for JavaScript, there&amp;rsquo;s typically a maximum number of features (records) that will be returned from any query &amp;ndash; usually set to 1000. If you want to get &lt;em>all&lt;/em> the features in the service, you&amp;rsquo;ll need to make multiple queries to the service. The best way to do this is with a recursive function that checks if the &lt;code>exceededTransferLimit&lt;/code> property is true, and if so will continue making additional queries until complete.&lt;/p>
&lt;p>One way to write that recursive function is like this&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-js" data-lang="js">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">_getAllFeaturesRecursive&lt;/span> &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#a6e22e">layer&lt;/span>, &lt;span style="color:#a6e22e">featuresSoFar&lt;/span>) =&amp;gt; {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">layer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">queryFeatures&lt;/span>({
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">start&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">featuresSoFar&lt;/span>.&lt;span style="color:#a6e22e">length&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">num&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">layer&lt;/span>.&lt;span style="color:#a6e22e">capabilities&lt;/span>.&lt;span style="color:#a6e22e">query&lt;/span>.&lt;span style="color:#a6e22e">maxRecordCount&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">outFields&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;*&amp;#39;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .&lt;span style="color:#a6e22e">then&lt;/span>((&lt;span style="color:#a6e22e">results&lt;/span>) =&amp;gt; {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// If &amp;#34;exceededTransferLimit&amp;#34; is true, then make another request (call
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// this same function) with a new &amp;#34;start&amp;#34; position. If not, return
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// with the concatenated results.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">results&lt;/span>.&lt;span style="color:#a6e22e">exceededTransferLimit&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">results&lt;/span>.&lt;span style="color:#a6e22e">exceededTransferLimit&lt;/span> &lt;span style="color:#f92672">===&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">_getAllFeaturesRecursive&lt;/span>(&lt;span style="color:#a6e22e">layer&lt;/span>, [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ...&lt;span style="color:#a6e22e">featuresSoFar&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ...&lt;span style="color:#a6e22e">results&lt;/span>.&lt;span style="color:#a6e22e">features&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ]);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> Promise.&lt;span style="color:#a6e22e">resolve&lt;/span>([...&lt;span style="color:#a6e22e">featuresSoFar&lt;/span>, ...&lt;span style="color:#a6e22e">results&lt;/span>.&lt;span style="color:#a6e22e">features&lt;/span>]);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> });
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> };&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;p>Wrapping that code in a function to kick it off and running it yields this example:&lt;/p>
&lt;p class="codepen" data-height="265" data-theme-id="light" data-default-tab="js,result" data-user="gavinr" data-slug-hash="QWEdgZw" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Query to Get ALL the Features - ArcGIS Maps SDK for JavaScript v4">
&lt;span>See the Pen &lt;a href="https://codepen.io/gavinr/pen/QWEdgZw">
Query to Get ALL the Features - ArcGIS Maps SDK for JavaScript v4&lt;/a> by Gavin Rehkemper (&lt;a href="https://codepen.io/gavinr">@gavinr&lt;/a>)
on &lt;a href="https://codepen.io">CodePen&lt;/a>.&lt;/span>
&lt;/p>
&lt;script async src="https://static.codepen.io/assets/embed/ei.js">&lt;/script>
&lt;p>Check out the full code &lt;a href="https://codepen.io/gavinr/pen/QWEdgZw?editors=0010">here&lt;/a>.&lt;/p>
&lt;p>&lt;em>Update&lt;/em>: My colleague &lt;a href="https://github.com/ycabon">Yann Cabon&lt;/a> mentioned that using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Generator_functions">ES6 Generator Functions&lt;/a>, if you have access to use them in your environment (&lt;a href="https://caniuse.com/es6-generators">caniuse&lt;/a>), might be an even easier way to do this. I concur! &lt;a href="https://codepen.io/ycabon/pen/GRqQdzj?editors=0012">Check out his Codepen example here&lt;/a>.&lt;/p>
&lt;p>&lt;em>Update 2022&lt;/em>: I&amp;rsquo;ve wrapped this logic up into a small package that you can use in your own project, called &lt;a href="https://github.com/gavinr/query-all-features">Query All Features&lt;/a>. Please try it out and let me know how it works for you: &lt;code>npm install query-all-features&lt;/code>.&lt;/p></description></item><item><title>My Favorite ArcGIS JavaScript API CodePens</title><link>https://gavinr.com/arcgis-js-api-codepens/</link><pubDate>Tue, 21 Jul 2020 00:00:00 -0500</pubDate><dc:creator>Gavin Rehkemper</dc:creator><guid>https://gavinr.com/arcgis-js-api-codepens/</guid><description>&lt;p>Here are some of my favorite code samples I&amp;rsquo;ve collected on &lt;a href="https://codepen.io/gavinr">my CodePen account&lt;/a> over the past few years.&lt;/p>
&lt;h2 id="centered-modal-geolocation-search">Centered Modal Geolocation Search&lt;/h2>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/djedBm">This CodePen&lt;/a> shows a modal with the &lt;a href="https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Search.html">Search widget&lt;/a> to allow a user to type in their location. When they search, the modal is hidden.&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/djedBm">&lt;p>&lt;video
autoplay="true" muted
loop="true"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/modal-search-zoom.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;h2 id="live-updating-protobuf-data-on-the-map">Live-Updating Protobuf Data on the Map&lt;/h2>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/XWbzGMW">This CodePen&lt;/a> gets current bus locations from a Protocol Buffer feed and shows them on the map using a client-side Feature Layer. I wrote more about this technique &lt;a href="https://gavinr.com/protocol-buffers-protobuf-browser/">on a blog post&lt;/a>.&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/XWbzGMW">&lt;p>&lt;video
autoplay="true" muted
loop="true"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/stl-bus-recording-5-min.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;h2 id="3d-smooth-animated-zooming">3D Smooth Animated Zooming&lt;/h2>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/xJjJVP">This CodePen&lt;/a> demonstrates the speed and easing options when moving between locations in the map.&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/xJjJVP">&lt;p>&lt;video
autoplay="true" muted
loop="true"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/arcgis-js-api-easing-zoom.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;h2 id="two-column-mapwidget-layout">Two-Column Map/Widget Layout&lt;/h2>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/qBddPKP">This CodePen&lt;/a> uses the &lt;a href="https://split.js.org/">Split.js JavaScript package&lt;/a> to create a draggable-sized sidebar with a widget (in this case, the Directions widget) in it.&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/qBddPKP">&lt;p>&lt;video
autoplay="true" muted
loop="true"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/sidebar-map.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;h2 id="show-feature-popup-on-mouse-hover">Show Feature Popup on Mouse Hover&lt;/h2>
&lt;p>When the mouse is hovering over a feature, &lt;a href="https://codepen.io/gavinr/pen/QWwjyxE">this CodePen&lt;/a> shows the Popup - debounced so that it only shows up when the mouse pauses.&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/QWwjyxE">&lt;p>&lt;video
autoplay="true" muted
loop="true"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/hover-popup-debounce.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;h2 id="hold-ctrl-to-zoom-when-scrolling-past-the-map">&amp;ldquo;Hold Ctrl to Zoom&amp;rdquo; When Scrolling Past the Map&lt;/h2>
&lt;p>Similar to Google Maps, &lt;a href="https://codepen.io/gavinr/pen/LKbxMy">in this CodePen&lt;/a> if the user is scrolling past the map on the page it will not zoom, but will also show a message telling the user they can &amp;ldquo;Use Ctrl + scroll to zoom the map.&amp;rdquo;&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/LKbxMy">&lt;img src="https://gavinr.com/posts/images/hold-ctrl-scroll.png" alt="hold ctrl to scroll">&lt;/a>&lt;/p>
&lt;h2 id="random-initial-location">Random Initial Location&lt;/h2>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/aXbxva">This CodePen&lt;/a> uses the JavaScript random function to calculate a random initial location for the map each time it loads.&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/aXbxva">&lt;p>&lt;video
autoplay="true" muted
loop="true"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/random-locations.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;h2 id="random-graphics">Random Graphics&lt;/h2>
&lt;p>Using some similar logic from above, &lt;a href="https://codepen.io/gavinr/pen/EOzVER">this CodePen&lt;/a> allows the user to place a bunch of random point locations on the map every time a button is clicked.&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/EOzVER">&lt;p>&lt;video
autoplay="true" muted
loop="true"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/random-graphics.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;h2 id="load-the-arcgis-maps-sdk-for-javascript-with-import-es-modules">Load the ArcGIS Maps SDK for JavaScript with Import (ES Modules)&lt;/h2>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/wvavjwp">This CodePen&lt;/a> &lt;a href="https://blog.codepen.io/2017/12/26/adding-typemodule-scripts-pens/">automatically detects&lt;/a> if you are loading an ESM (ES Modules) file on the page, so you can use Esri Loader&amp;rsquo;s ESM build to load a map into the page - no &lt;code>script&lt;/code> tags required!&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/wvavjwp">&lt;img src="https://gavinr.com/posts/images/js-api-esm.png" alt="arcgis js api - es modules">&lt;/a>&lt;/p>
&lt;h2 id="add-a-feature-layer-via-url">Add a Feature Layer via URL&lt;/h2>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/eLgpva">This CodePen&lt;/a> adds a simple form element where the user can copy/paste their own Feature Layer url and see it on the map.&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/eLgpva">&lt;p>&lt;video
autoplay="true" muted
loop="true"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/add-feature-layer.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;h2 id="custom-widget-management">Custom Widget Management&lt;/h2>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/ebzava">This CodePen&lt;/a> shows how to use the &amp;ldquo;Container&amp;rdquo; property of ArcGIS Maps SDK for JavaScript widgets to place them into the DOM in a specific place.&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/ebzava">&lt;p>&lt;video
autoplay="true" muted
loop="true"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/js-api-custom-widget-management.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;h2 id="add-a-header-to-the-expand-widget">Add a Header to the Expand Widget&lt;/h2>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/GPXLey">This CodePen&lt;/a> adds a header to the Expand Widget, which might be useful for situations in which you want to add instructions of explanatory text in the Expand widget.&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/GPXLey">&lt;img src="https://gavinr.com/posts/images/header-basemap-selector.png" alt="alt text">&lt;/a>&lt;/p>
&lt;h2 id="animate-go-to-extent">Animate Go To Extent&lt;/h2>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/LgpXON">This CodePen&lt;/a> has a button to animate the zoom into a location on the map. It&amp;rsquo;s pretty simple, just call &lt;code>view.goTo(extent);&lt;/code>&lt;/p>
&lt;p>&lt;a href="https://codepen.io/gavinr/pen/LgpXON">&lt;p>&lt;video
autoplay="true" muted
loop="true"
style="display:block; margin: 0 auto; max-width: 100%;"
>
&lt;source src="https://gavinr.com/posts/videos/animate-zoom.mp4" type="video/mp4" />
&lt;/video>&lt;/p>&lt;/a>&lt;/p>
&lt;p>Check out these and even more in my &lt;a href="https://codepen.io/collection/DLyYxE">ArcGIS JavaScript API Map Demos collection&lt;/a> on CodePen. Thanks!&lt;/p></description></item></channel></rss>