<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>GeoDienstenCentrum Blog</title>
    <subtitle>Over toegankelijke ruimtelijke informatievoorziening</subtitle>
    <link href="https://geodienstencentrum.github.io/atom.xml" rel="self" type="application/atom+xml"/>
    <link href="https://geodienstencentrum.github.io/rss.xml" rel="self" type="application/rss+xml"/>
    <link href="https://geodienstencentrum.github.io/"/>
    <updated>2026-05-28T13:23:10+02:00</updated>
    <id>https://geodienstencentrum.github.io/</id>
    <author>
        <name>GeoDienstenCentrum</name>
        <email>mprins@users.sf.net</email>
    </author>
    <rights>© 2026 GeoDienstenCentrum</rights>
    <icon>/favicon.png</icon>

<!-- static -->
    <entry>
        <title>homepage</title>
        <link href="https://geodienstencentrum.github.io/" />
        <updated>2026-05-28T13:23:10+02:00</updated>
        <author>
            <name>GeoDienstenCentrum</name>
            <uri>https://geodienstencentrum.github.io/</uri>
            <email>mprins@users.sf.net</email>
        </author>
        <id>https://geodienstencentrum.github.io/</id>
        <summary></summary>
        <content type="text">Voor advies over en implementatie van toegankelijke ruimtelijke informatie.</content>
        <category term="homepage"/>
    </entry>
    <entry>
        <title>sitemap</title>
        <link href="https://geodienstencentrum.github.io/sitemap.html" />
        <updated>2026-05-28T13:23:10+02:00</updated>
        <author>
            <name>GeoDienstenCentrum</name>
            <uri>https://geodienstencentrum.github.io/</uri>
            <email>mprins@users.sf.net</email>
        </author>
        <id>https://geodienstencentrum.github.io/sitemap.html</id>
        <summary></summary>
        <content type="text">Sitemap voor GeoDienstenCentrum Blog</content>
        <category term="sitemap"/>
    </entry>
<!-- posts -->

    <entry>
        <title>DokuWikiSpatial: spatial indexing and search for your wiki</title>
        <link href="https://geodienstencentrum.github.io/blog/dokuwiki/webmapping/2014-09-17/dokuwikispatial_indexing.html"/>
        <!-- <published>2003-12-13T09:17:51-08:00</published> -->
        <updated>2014-09-17T10:00:00+02:00</updated>
        <author>
            <name>GeoDienstenCentrum</name>
            <uri>https://geodienstencentrum.github.io/</uri>
            <email>mprins@users.sf.net</email>
        </author>
        <id>https://geodienstencentrum.github.io/blog/dokuwiki/webmapping/2014-09-17/dokuwikispatial_indexing</id>
        <summary>Adding geohash based spatial indexing and search capabilities to DokuWiki.</summary>
        <content type="html">&lt;h2 id=&quot;indexing&quot;&gt;Indexing&lt;/h2&gt;

&lt;p&gt;Now that we can add location to our wiki pages using the &lt;a href=&quot;/blog/webmapping/dokuwiki/2014-04-14/dokuwikispatial_mapping.html&quot;&gt;mapping&lt;/a&gt; and &lt;a href=&quot;/blog/webmapping/dokuwiki/2014-07-16/dokuwikispatial_geotag.html&quot;&gt;geotagging&lt;/a&gt; plugins discussed in previous posts lets start making use of that data. Next to the &lt;abbr title=&quot;Search Engine Optimization&quot;&gt;SEO&lt;/abbr&gt; benefits it would be nice to be able to use that data for generating information. To start off this data needs to be made searchable in a fast manner, this is done by creating a (spatial) index.&lt;/p&gt;

&lt;p&gt;The chosen index algorithm is based on a value calculated from the coordinate pair, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Geohash&quot;&gt;geohash&lt;/a&gt;. This hash provides a one dimensional representation of a coordinate pair with the length of the hash being a measure for the accuracy of the coordinates. For example the coordinates &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(57.64911 10.40744)&lt;/code&gt; gives a hash of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u4pruydqqvj&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(57.6 10.4)&lt;/code&gt; gives a hash of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u4pru&lt;/code&gt;. A big advantage is that this can be easily stored in an array with the geohash as a key and the resource(s) as value. Using PHP’s built-in serialisation it is stored on disk in plain text, just like the other indexes and wiki metadata.&lt;/p&gt;

&lt;p&gt;As part of the indexing both a &lt;a href=&quot;https://en.wikipedia.org/wiki/Keyhole_Markup_Language&quot;&gt;KML&lt;/a&gt; and a &lt;a href=&quot;https://en.wikipedia.org/wiki/GeoRSS&quot;&gt;GeoRSS&lt;/a&gt; file are generated, these can be served up as a spatial sitemap but may also be used in a map on the wiki. Also, as DokuWiki provides support for &lt;a href=&quot;https://en.wikipedia.org/wiki/Exchangeable_image_file_format#Geolocation&quot;&gt;EXIF&lt;/a&gt; data in images, when uploading JPEG or TIFF media into the wiki’s media store these are added to the spatial index as well if they have the proper EXIF GPS tags.&lt;/p&gt;

&lt;h2 id=&quot;searching&quot;&gt;Searching&lt;/h2&gt;

&lt;p&gt;The most typical question for generating information is “What is near (to)?…” In case of the wiki resources this would yield one or more pages or images.&lt;/p&gt;

&lt;p&gt;Looking back at the example above note that there is an overlap in the hash, this is another benefit of using the geohash. This allows selective matching implicitly enabling the use of a bounding box search ie. longer geohashes specify a more accurate location but in reverse also a smaller serach area.&lt;/p&gt;

&lt;p&gt;A small drawback with using a geohash this way is that the positional error and boundingbox grow rapidly with shortening geohash length. For example, a geohash of five characters (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u4pru&lt;/code&gt;) has an error of ±2.4km where a geohash that is three characters shorter (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u4&lt;/code&gt;) has a positional error of ±630km. This means that when doing hash based lookups the actual search location is not static with shortening the hash/enlarging the bounds. This requires some more work, but for the initial 0.1 release of the &lt;a href=&quot;https://www.dokuwiki.org/plugin:spatialhelper&quot;&gt;plugin&lt;/a&gt; it is sufficient.&lt;/p&gt;

&lt;p&gt;The plugin integrates with the geotag plugin to link to a page with dynamic search results. So a geotag with coordinates &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;48º11&apos;36.384&quot;N;16º27&apos;39.06&quot;E&lt;/code&gt; links to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?do=findnearby&amp;amp;lat=48.19344&amp;amp;lon=16.46085&lt;/code&gt; which initially does a lookup in the index for a geohash of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u2ednt67js&lt;/code&gt;. This will render as a html page with a list of results. The search interface will be augmented to support other output formats, eg. a complete map or a GeoRSS document are also possibilities.&lt;/p&gt;

&lt;figure id=&quot;screen&quot;&gt;
  &lt;img src=&quot;/img/2014-09-17-findnearbyresult.png&quot; alt=&quot;search results screen capture&quot; /&gt;
  &lt;figcaption&gt;An example of a list of search results on a wiki page of a
        &lt;a href=&quot;http://wild-water.nl/dokuwiki/start?do=findnearby&amp;amp;geohash=u0urcr&quot;&gt;
        findnearby to 50.62ºN;6.04ºE&lt;/a&gt;.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Some more examples are available on the &lt;a href=&quot;https://dokuwikispatial.sourceforge.io/dokuwiki/doku.php/spatialhelper/start&quot;&gt;sample site&lt;/a&gt; and &lt;a href=&quot;https://wild-water.nl/dokuwiki/start?do=findnearby&amp;amp;geohash=u0urcr&quot;&gt;wild-water.nl&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://twitter.com/GeoDiensten/status/512158204290408448&quot;&gt;Talk about this on twitter&lt;/a&gt;.&lt;/p&gt;
</content>
        <category term="dokuwiki"/><category term="webmapping"/>
    </entry>

    <entry>
        <title>DokuWikiSpatial: geotagging for your wiki</title>
        <link href="https://geodienstencentrum.github.io/blog/webmapping/dokuwiki/2014-07-16/dokuwikispatial_geotag.html"/>
        <!-- <published>2003-12-13T09:17:51-08:00</published> -->
        <updated>2014-07-16T15:31:00+02:00</updated>
        <author>
            <name>GeoDienstenCentrum</name>
            <uri>https://geodienstencentrum.github.io/</uri>
            <email>mprins@users.sf.net</email>
        </author>
        <id>https://geodienstencentrum.github.io/blog/webmapping/dokuwiki/2014-07-16/dokuwikispatial_geotag</id>
        <summary>Adding geotagging capabilities to DokuWiki using a custom syntax plugin.</summary>
        <content type="html">&lt;h2 id=&quot;geotagging&quot;&gt;Geotagging&lt;/h2&gt;

&lt;p&gt;After adding mapping capabilities to your wiki using the &lt;a href=&quot;/blog/webmapping/dokuwiki/2014-04-14/dokuwikispatial_mapping.html&quot;&gt;openlayersmap plugin&lt;/a&gt; we will now look into actually creating spatial data as part of your content using geotagging. &lt;a href=&quot;http://en.wikipedia.org/wiki/Geotagging&quot;&gt;Geotagging&lt;/a&gt; is the process of adding geographic (meta) data to content, in our case wiki pages.&lt;/p&gt;

&lt;p&gt;To accomplish this a &lt;a href=&quot;https://www.dokuwiki.org/plugin:geotag&quot;&gt;syntax plugin&lt;/a&gt; was developed which allows adding the relevant data to the page. An example of this syntax is shown in the following code snippet.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
{{geotag&amp;gt;lat:48.19344, lon:16.46085, placename:VERBUND-Wasserarena,
    country:AT, region:AT-9}}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This syntax is parsed and rendered as part of the page metadata:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;geo.region&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AT-9&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;geo.placename&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;VERBUND-Wasserarena&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;geo.position&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;48.19344;16.46085&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;geo.country&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AT&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ICBM&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;48.19344, 16.46085&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;geo.geohash&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;u2ednt67js&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DC.title&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nieuwe Wildwaterbaan Donau Insel, Wenen&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This metadata is also stored in the wiki’s metadata system so that it can be indexed and searched. When using a plugin such as &lt;a href=&quot;https://www.dokuwiki.org/plugin:socialcards&quot;&gt;socialcards&lt;/a&gt; the appropriate &lt;a href=&quot;http://ogp.me/&quot;&gt;OpenGraph&lt;/a&gt; elements are also exported in the page headers.&lt;/p&gt;

&lt;p&gt;The geotag is rendered as part of the page content/body in the form of a &lt;a href=&quot;http://microformats.org/wiki/geo&quot;&gt;geo microformat&lt;/a&gt; and a &lt;a href=&quot;http://schema.org/Place&quot;&gt;schema.org Place&lt;/a&gt;. This allows indexing of the page location by search engines such as &lt;a href=&quot;https://help.yandex.com/webmaster/schema-org/semantic-faq.xml&quot;&gt;Yandex&lt;/a&gt;, &lt;a href=&quot;http://www.bing.com/webmaster/help/marking-up-your-site-with-structured-data-3a93e731&quot;&gt;Bing&lt;/a&gt;  and &lt;a href=&quot;https://support.google.com/webmasters/answer/1211158&quot;&gt;Google&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;geotagPrint&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Geotag (locatie) voor: &lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;geo&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Geotag (locatie) voor VERBUND-Wasserarena&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;itemscope&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemtype=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://schema.org/Place&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemprop=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;VERBUND-Wasserarena&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;:&lt;span class=&quot;ni&quot;&gt;&amp;amp;nbsp;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wildwaterbaan_donau_insel_wenen?do=findnearby&amp;amp;amp;lat=48.19344&amp;amp;amp;lon=16.46085&quot;&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Zoek in de buurt van VERBUND-Wasserarena&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemprop=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;geo&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemscope&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemtype=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://schema.org/GeoCoordinates&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;latitude&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemprop=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;latitude&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;48.19344&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;48º11&apos;36.384&quot;N&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;longitude&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;itemprop=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;longitude&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;16.46085&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;16º27&apos;39.06&quot;E&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;a11y&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Zoek in de buurt van VERBUND-Wasserarena&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which looks something like the &lt;a href=&quot;#screen&quot;&gt;figure&lt;/a&gt; below in the default DokuWiki layout.&lt;/p&gt;

&lt;figure id=&quot;screen&quot;&gt;
  &lt;img src=&quot;/img/2014-07-16-geotag.png&quot; alt=&quot;geotag example screen capture&quot; /&gt;
  &lt;figcaption&gt;An example of a rendered geotag on a wiki page locating the
    VERBUND-Wasserarena at 48º11&apos;36.384&quot;N;16º27&apos;39.06&quot;E.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Using the geotags on your pages opens up other ways of exploring and viewing your pages. One example is using the content in an augmented reality application such as &lt;a href=&quot;http://www.mixare.org/&quot;&gt;Mixare&lt;/a&gt;. Another is finding pages that are located nearby to the current page or using a map as a browsing interface for exploration of yout wiki.&lt;/p&gt;

&lt;p&gt;Read more posts in this series on:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/webmapping/dokuwiki/2014-04-14/dokuwikispatial_mapping.html&quot;&gt;mapping&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/dokuwiki/webmapping/2014-09-17/dokuwikispatial_indexing.html&quot;&gt;indexing and search&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://twitter.com/GeoDiensten/status/489358340515176448&quot;&gt;Talk about this on twitter&lt;/a&gt;.&lt;/p&gt;
</content>
        <category term="webmapping"/><category term="dokuwiki"/>
    </entry>

    <entry>
        <title>DokuWikiSpatial: maps for your wiki</title>
        <link href="https://geodienstencentrum.github.io/blog/webmapping/dokuwiki/2014-04-14/dokuwikispatial_mapping.html"/>
        <!-- <published>2003-12-13T09:17:51-08:00</published> -->
        <updated>2014-04-14T23:31:00+02:00</updated>
        <author>
            <name>GeoDienstenCentrum</name>
            <uri>https://geodienstencentrum.github.io/</uri>
            <email>mprins@users.sf.net</email>
        </author>
        <id>https://geodienstencentrum.github.io/blog/webmapping/dokuwiki/2014-04-14/dokuwikispatial_mapping</id>
        <summary>A brief introduction to DokuWiki and the mapping capabilities provided by the openlayersmap plugin.</summary>
        <content type="html">&lt;h2 id=&quot;spatially-enable-your-wiki-part-1-mapping&quot;&gt;Spatially enable your Wiki, part 1: mapping&lt;/h2&gt;

&lt;p&gt;In this series we will look at spatially enabling the DokuWiki system by adding mapping, data management and spatial indexing with the help of geotagging and other means. In general this functionality is described using the term GeoCMS and are provided as plugins by the &lt;a href=&quot;http://dokuwikispatial.sourceforge.net/dokuwiki/doku.php&quot;&gt;DokuwikiSpatial project&lt;/a&gt;. In this first post we’ll look at mapping after quick introduction to the base &lt;a href=&quot;https://www.dokuwiki.org/&quot;&gt;DokuWiki&lt;/a&gt; stack.&lt;/p&gt;

&lt;h2 id=&quot;about-dokuwiki&quot;&gt;About DokuWiki&lt;/h2&gt;

&lt;p&gt;The Dokuwiki software is a plain text driven PHP powered wiki engine with a well defined API and plugin mechanism. A big advantage of having a plain text storage is that you can easily run it from a USB stick (eg. &lt;a href=&quot;https://www.dokuwiki.org/install:dokuwiki_on_a_stick&quot;&gt;DokuWiki on a stick&lt;/a&gt; or &lt;a href=&quot;https://www.dokuwiki.org/install?s[]=portable#alternative_install_methods&quot;&gt;other portable methods&lt;/a&gt;, another feature is that its easy to set up and manage because there is just the webserver to handle, contrary to most other wiki software that requires some sort of SQL-enabled back-end.&lt;/p&gt;

&lt;p&gt;At the time I started using DokuWiki some seven years ago there were already some plugin’s that allowed putting a map in a page, however these did not fit my bill of having free basemap data and user editable content for overlays or points of interest. Also they suffer from major accessibility issues. Having only a little experience using PHP at the time I looked into the plugin system and found a well &lt;a href=&quot;http://xref.dokuwiki.org/reference/dokuwiki/nav.html?index.html&quot;&gt;documented API&lt;/a&gt; and extensive list of samples kick-starting me to write my own mapping plugin for the wiki, &lt;a href=&quot;https://www.dokuwiki.org/plugin:openlayersmap&quot;&gt;openlayersmap&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;maps-in-your-wiki&quot;&gt;Maps in your wiki&lt;/h2&gt;

&lt;p&gt;As the name suggests the openlayersmap pluging uses the &lt;a href=&quot;http://openlayers.org&quot;&gt;OpenLayers library&lt;/a&gt;. It has a choice of both free and proprietary basemap options &lt;a href=&quot;http://www.openstreetmap.org/about&quot;&gt;OSM&lt;/a&gt; or &lt;a href=&quot;http://developer.mapquest.com/products/maps/&quot;&gt;MapQuest&lt;/a&gt; and Bing or Google if you really want that.&lt;/p&gt;

&lt;p&gt;The latest version (4.0) of the openlayersmap plugin enables users to add wiki markup to a page that contains a simple configuration for the map such as dimensions, initial location and initial scale. It also allows for entering a list of points of interest with a descriptive text and a symbol layout (image, rotation, opacity). Next to having a list of points a GPX, KML or GeoJSON file may be loaded from the wiki’s media directory. The POI data, just like the media files is actually part of the page/wiki so that it can be indexed and queried and the initial location of the map is added to the page metadata so it can be used by internal and external search engines.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/img/2014-04-12-openlayersmap.png&quot; alt=&quot;screen capture an example map&quot; /&gt;
  &lt;figcaption&gt;An example of the slippy map showing a popup with a photograph of the Gumpen waterfall in the Loisach. The wiki markup for this is listed below&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;olmap&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olmap&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;660px&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;400px&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lat=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;47.48&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lon=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;10.98&quot;&lt;/span&gt;
   &lt;span class=&quot;na&quot;&gt;zoom=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;13&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;statusbar=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;baselyr=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;landscape&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
47.446383,10.918047,0,.8,stuw.png,Gumpen waterval \\
 {{http://www.hooidonksekanoclub.nl/fotoalbum/2009-05-hemelvaart/slides/IMG_7114.jpg?150|Gumpen waterval gezien van stroomaf&quot;}}
47.452819,10.923728,0,.8,uitstap.png,uitstap bovenloop Loisach
47.482083,10.989167,0,.8,instap.png,Instap Gschwandsteg
47.48146,11.04633,0,.8,uitstap.png, Uitstap &quot;Zielhaus Grainau&quot;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/olmap&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the rendered page the map is available both as a static image with an associated table listing the points of interest and as slippy map that provides dynamic navigation and information display (progressive enhancement). The slippy map can be used (navigated and queried) using both the keyboard and pointing devices. (For more on this see: &lt;a href=&quot;/blog/accessibility/webmapping/2014-02-14/enhancing-openlayers-controls.html&quot;&gt;Enhancing OpenLayers control  accessibility&lt;/a&gt;)
The static image and table are used when printing and may also be used by screen readers (actually this needs a little more work) and provide a fall-back mechanism should the browser not (properly) support javascript or CSS.&lt;/p&gt;

&lt;p&gt;Stay tuned for other posts in this series on:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/webmapping/dokuwiki/2014-07-16/dokuwikispatial_geotag.html&quot;&gt;geotagging&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/dokuwiki/webmapping/2014-09-17/dokuwikispatial_indexing.html&quot;&gt;indexing and search&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://twitter.com/GeoDiensten/status/455822576007528448&quot;&gt;Talk about this on twitter&lt;/a&gt;.&lt;/p&gt;
</content>
        <category term="webmapping"/><category term="dokuwiki"/>
    </entry>

    <entry>
        <title>Enhancing OpenLayers control accessibility</title>
        <link href="https://geodienstencentrum.github.io/blog/accessibility/webmapping/2014-02-14/enhancing-openlayers-controls.html"/>
        <!-- <published>2003-12-13T09:17:51-08:00</published> -->
        <updated>2014-02-14T18:31:00+01:00</updated>
        <author>
            <name>GeoDienstenCentrum</name>
            <uri>https://geodienstencentrum.github.io/</uri>
            <email>mprins@users.sf.net</email>
        </author>
        <id>https://geodienstencentrum.github.io/blog/accessibility/webmapping/2014-02-14/enhancing-openlayers-controls</id>
        <summary>Enhancing OpenLayers interoperability and keyboard accessibility by extending the default controls. A short description of some modifications and extensions of the original OpenLayers code.</summary>
        <content type="html">&lt;p&gt;Most &lt;a href=&quot;http://openlayers.org/&quot;&gt;OpenLayers&lt;/a&gt; control widgets suffer from poorly designed or missing keyboard interoperability. Some attempts have been made to enhance (&lt;a href=&quot;http://wet-boew.github.io/wet-boew/docs/ref/geomap/geomap-en.html&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://github.com/openlayers/openlayers/pull/425&quot;&gt;2&lt;/a&gt;) these shortcomings. However these changes and enhancements have not landed, are difficult to implement or carry a burden of extra javascript frameworks. Also they don’t address some of the semantic issues that are present in OpenLayers generated markup.&lt;/p&gt;

&lt;p&gt;I have extended some of the most used controls to be keyboard accessible and have enhanced usability by adding tooltips as part of the markup.&lt;/p&gt;

&lt;h2 id=&quot;zoom-control&quot;&gt;Zoom control&lt;/h2&gt;

&lt;p&gt;The problem with the original zoom control is that it uses a hash hyperlink (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;a href=&quot;#&quot; /&amp;gt;&lt;/code&gt; element) for something that is an action. Hyperlinks are supposed to navigate somewhere within a page with a consistent manner, eg. clicking the zoom in link should always take you to the same place within the page. This is not the case, clicking the link more than once does not always take you to the same place. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchor&lt;/code&gt; element is really misused to emulate a button, people smarter than me have explained that &lt;a href=&quot;http://www.nczonline.net/blog/2013/01/29/you-cant-create-a-button/&quot;&gt;you can’t create a button&lt;/a&gt; and &lt;a href=&quot;http://www.karlgroves.com/2013/05/14/links-are-not-buttons-neither-are-divs-and-spans/&quot;&gt;links are not buttons&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that the before/after code snippets below have been abbreviated by shortening style, class and id attributes.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;before&quot;&gt;Before&lt;/h3&gt;
&lt;p&gt;Markup of the original:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;unselectable=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;on&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#zoomIn&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olControlZoomIn olButton&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;+&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#zoomOut&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olControlZoomOut olButton&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;-&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;after&quot;&gt;After&lt;/h3&gt;
&lt;p&gt;The enhancement consists of replacing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchor&lt;/code&gt; element with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;button&lt;/code&gt;. The good thing of using a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;button&lt;/code&gt; is that it allows for additional markup inside the element, giving us room for a tooltip. The tooltip &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;span&lt;/code&gt; element of the button is made visible on :hover and :focus using regular css, the tooltip also greatly enhances screen reader interoperability.&lt;/p&gt;

&lt;p&gt;Modified and enhanced markup:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;unselectable=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;on&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olControlZoomIn olButton olHasTooltip_bttm_r&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;role=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tooltip&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Zoom in&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    +
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olControlZoomOut olButton olHasTooltip_bttm_r&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;role=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tooltip&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Zoom uit&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    −
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These modifications were proposed in &lt;a href=&quot;https://github.com/openlayers/ol3/pull/1708&quot;&gt;PR
1708&lt;/a&gt; and &lt;a href=&quot;https://github.com/openlayers/openlayers/pull/1249&quot;&gt;PR 1249&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;layerswitcher&quot;&gt;LayerSwitcher&lt;/h2&gt;

&lt;p&gt;The LayerSwitcher suffers from some of the same problems as noted above, with the difference that the buttons to activate (expand / collapse) the control are actually &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt;’s with images with an associated mouseclick handler. The bigger (compared to hyperlinks) problem with this is that these are only available to users with a pointing device.&lt;/p&gt;

&lt;h3 id=&quot;before-1&quot;&gt;Before&lt;/h3&gt;
&lt;p&gt;Markup of the original:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olControlLayerSwitcher...&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;unselectable=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;on&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;layersDiv&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;display: none;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;baseLbl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Achtergrondkaart&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;baseLayersDiv&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;radio&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0 buffer: OpenLayers WMS&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;checked=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olButton&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;labelSpan olButton&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;0 buffer: OpenLayers WMS&lt;span class=&quot;nt&quot;&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;br&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dataLbl&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Overlays&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dataLayersDiv&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;maximizeDiv olButton&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;../img/layer-switcher-maximize.png&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;minimizeDiv olButton&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;../img/layer-switcher-minimize.png&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;after-1&quot;&gt;After&lt;/h3&gt;

&lt;p&gt;Again the solution here is to use the proper semantic element for the expand and collapse actions; a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;button&lt;/code&gt;. Next to that, to enhance usability, the buttons are moved to the top of the control so they end up as first element in the tab order. The images were replaced with the ubiquitous hamburger symbol &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;≡&lt;/code&gt; for opening and a multiply symbol &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;×&lt;/code&gt; for collapsing the popover. Also extra focus handling was applied so that when expanding the control focus is moved to the first option that can be selected and when closing the control focus is moved back to the map (the map’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; element needs to be made programatically focusable by adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tabindex=&quot;-1&quot;&lt;/code&gt;), next to that the selected option or checkbox remains selected until the LayerSwitcher is closed.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olControlLayerSwitcher...&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;unselectable=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;on&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;show&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;maximizeDiv olButton...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;role=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tooltip&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Toon kaartlagen&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      ≡
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hide&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;minimizeDiv olButton...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;role=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tooltip&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Verberg kaartlagen&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      ×
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;layersDiv&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;baseLbl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Achtergrondkaart&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;baseLayersDiv&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;baseLayersDiv&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;radio&quot;&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;OpenStreetMap&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;checked=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olButton&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;labelSpan olButton&quot;&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;OpenStreetMap&lt;span class=&quot;nt&quot;&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;br&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dataLbl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Overlays&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dataLayersDiv&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;POI&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;checkbox&quot;&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;POI&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;checked=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olButton&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;labelSpan olButton&quot;&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;POI&lt;span class=&quot;nt&quot;&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;br&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;This could be enhanced a little further by explicitly linking the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;label&lt;/code&gt; and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input&lt;/code&gt; elements using a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for&lt;/code&gt; attribute or nesting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input&lt;/code&gt; elements inside their labeling element, however the above changes are enough to make the control keyboard operable.&lt;/em&gt;&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/img/2014-02-14-enhancing-openlayers-controls.png&quot; alt=&quot;Screen capture showing enhanced popup&quot; /&gt;
  &lt;figcaption&gt;The enhanced FramedCloud popup and KeyboardClick controls in action. Showing the tooltip on
  keyboard focus of the close button on the popup.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;overviewmap-control&quot;&gt;OverviewMap control&lt;/h2&gt;

&lt;p&gt;The OverviewMap is a widget that presents a small map with an indication of the bounding box of the parent map, the indicator may be moved using a pointing device thus doubling in function as a navigating tool as well. This control is using the same pattern as the LayerSwitcher.&lt;/p&gt;

&lt;h3 id=&quot;before-2&quot;&gt;Before&lt;/h3&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olControlOverviewMap...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;unselectable=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;on&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olControlOverviewMapElement&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olMap&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olMapViewport&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;dir=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ltr&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olLayerDiv olLayerGrid&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olTileImage&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olControlOverviewMapExtentRectangle&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olControlOverviewMapMaximizeButton&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olControlOverviewMapMaximizeButton olButton&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olControlOverviewMapMaximizeButton_innerImage&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olAlphaImg&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;../img/layer-switcher-maximize.png&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;OpenLayers_Control_minimizeDiv&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olControlOverviewMapMinimizeButton olButton&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;OpenLayers_Control_minimizeDiv_innerImage&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olAlphaImg&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;../img/layer-switcher-minimize.png&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;after-2&quot;&gt;After&lt;/h3&gt;
&lt;p&gt;I’ve replaced the images with proper buttons like the LayerSwitcher and added tooltips. The navigation function hasn’t been touched yet, my experience shows that even experienced users hardly know how to find this and is rarely used. Also since the map responds to the regular arrow keys on the keyboard, adding this function to the overview does not seem neccesary.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olOverviewMap...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;unselectable=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;on&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olOverviewMapElement&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olMap&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olMapViewport&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;dir=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ltr&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olLayerDiv olLayerGrid&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olTileImage&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olOverviewMapExtentRectangle&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;show&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olOverviewMapMaximizeButton
        olOverviewMapButton olButton olHasTooltip&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;role=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tooltip&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Toon overzicht&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    +
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hide&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;olOverviewMapMinimizeButton
        olOverviewMapButton olButton olHasTooltip&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;role=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tooltip&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Verberg overzicht&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    ×
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;framedcloud-popup-and-feature-info-control&quot;&gt;FramedCloud popup and feature info control&lt;/h2&gt;

&lt;p&gt;The information popup I tend to use most is the FramedCloud popup. It is the most feature rich of the available popups. The popup provides a dynamic panel floating over the map to show information to the user. Most commonly it will display attribute information of a feature in the map as a result of a user interaction with eg. a &lt;a href=&quot;http://dev.openlayers.org/apidocs/files/OpenLayers/Control/SelectFeature-js.html&quot;&gt;SelectFeature&lt;/a&gt; or a &lt;a href=&quot;http://dev.openlayers.org/apidocs/files/OpenLayers/Control/WMTSGetFeatureInfo-js.html&quot;&gt;FeatureInfo&lt;/a&gt; control.&lt;/p&gt;

&lt;p&gt;Markup-wise this control isn’t that interesting so I’ll spare you the code. The problem with the popup is that because it uses a clickable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; with a background image it firstly may be hard to find and secondly it won’t react to key events, no focus, no click thus impossible to close without a pointing device. To fix it I inserted a tooltip enabled &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;button&lt;/code&gt; as above and added a focus handler to move focus to the popup when it opens. When the popup is closed focus is moved back to the map.&lt;/p&gt;

&lt;p&gt;To actually retrieve the attribute information in a keyboard friendly manner &lt;a href=&quot;https://github.com/elemoine&quot;&gt;Eric Lemoine&lt;/a&gt; created the &lt;a href=&quot;https://github.com/GeoDienstenCentrum/openlayers/blob/master/examples/accessible-click-control.js&quot;&gt;KeyboardClick&lt;/a&gt; control. This control enables moving a cursor on-screen using the arrow keys. With some additional code in the click handler it will select the first feature it finds closeby to the cursor.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;onClick&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;geometry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lyrs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selectControl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;selTarget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;px&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getPixelFromLonLat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
               &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;OpenLayers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;LonLat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;geometry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;geometry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// create a small polygon around the click&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;px&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;STEP_SIZE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lonlat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getLonLatFromPixel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;radius&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lonlat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;geometry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sides&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rotation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;clicked&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;OpenLayers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Geometry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Polygon&lt;/span&gt;
                  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createRegularPolygon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;geometry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sides&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rotation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// hit detection, the first intersection is a hit&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;resized&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;resized&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;resized&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// try a few (resized-1) times with larger click polygon each time&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;clicked&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;clicked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;geometry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lyrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lyrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getVisibility&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lyrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;nx&quot;&gt;selTarget&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lyrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clicked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;intersects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selTarget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;geometry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selectControl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clickFeature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selTarget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When using WMS or WMTS layers this code can be limited to passing the coordinate pair of the click location to a feature info control as is done in the &lt;a href=&quot;https://github.com/mprins/CBSviewer/blob/master/src/main/js/KeyboardClick.js#L52&quot;&gt;CBS viewer project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For some of the other javascript and Sass code you can look into the &lt;a href=&quot;https://github.com/mprins/dokuwiki-plugin-openlayersmap/tree/master/javascript&quot;&gt;openlayersmap&lt;/a&gt; &lt;a href=&quot;https://www.dokuwiki.org/plugin:openlayersmap&quot;&gt;DokuWiki plugin&lt;/a&gt; source tree.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://twitter.com/GeoDiensten/status/434063976347860992&quot;&gt;Talk about this on twitter&lt;/a&gt;.&lt;/p&gt;
</content>
        <category term="accessibility"/><category term="webmapping"/>
    </entry>

    <entry>
        <title>CBSviewer, an accessible, open standards based webmap viewer</title>
        <link href="https://geodienstencentrum.github.io/blog/accessibility/webmapping/2013-04-12/cbsviewer-an-accessible-open-standards-based-viewer.html"/>
        <!-- <published>2003-12-13T09:17:51-08:00</published> -->
        <updated>2013-04-12T15:31:00+02:00</updated>
        <author>
            <name>GeoDienstenCentrum</name>
            <uri>https://geodienstencentrum.github.io/</uri>
            <email>mprins@users.sf.net</email>
        </author>
        <id>https://geodienstencentrum.github.io/blog/accessibility/webmapping/2013-04-12/cbsviewer-an-accessible-open-standards-based-viewer</id>
        <summary>Developing a webmapping application together with Statistics Netherlands to replace their current offerings of webmapping such as 'CBS in uw Buurt' which have various accessibility issues and has Google looking in over your shoulder.</summary>
        <content type="html">&lt;p&gt;The past months I’ve been busy developing a web mapping application together with &lt;a href=&quot;http://www.cbs.nl/&quot;&gt;Statistics Netherlands&lt;/a&gt; to replace their current offerings of web mapping such as &lt;a href=&quot;http://www.cbsinuwbuurt.nl/&quot;&gt;CBS in uw Buurt&lt;/a&gt; which have various accessibility issues and has Google looking in over your shoulder. The new application can be used with both the keyboard and a mouse and and will fallback to a non CSS and/or non Javascript version if needed (or requested) by the user providing a much better and safer experience.&lt;/p&gt;

&lt;p&gt;Key features of the application are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;open standards based interfaces &lt;a href=&quot;http://www.opengeospatial.org/standards/wms&quot; title=&quot;Web Map Server specifications&quot;&gt;WMS&lt;/a&gt;, &lt;a href=&quot;http://www.opengeospatial.org/standards/wmts&quot; title=&quot;Web Map Tile Service specifications&quot;&gt;WMTS&lt;/a&gt;, &lt;a href=&quot;http://www.opengeospatial.org/standards/ols&quot; title=&quot;Open Location Service specification&quot;&gt;OpenLS LUS&lt;/a&gt; and &lt;a href=&quot;http://www.w3.org/TR/WCAG/&quot; title=&quot;Web Content Accessibility Guidelines specification&quot;&gt;WCAG&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;easy modification using &lt;a href=&quot;http://maven.apache.org/plugins/maven-war-plugin/overlays.html&quot; title=&quot;WAR Overlays&quot;&gt;maven war overlay techniques&lt;/a&gt; (as an example you can look into the &lt;a href=&quot;https://github.com/MinELenI/NOKviewer&quot;&gt;NOK viewer project on Github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;easy to localize using property files / resource bundles for all the text&lt;/li&gt;
  &lt;li&gt;easy to configure thematic maps using a set of xml files&lt;/li&gt;
  &lt;li&gt;easy styling adjustments using Sass and modular CSS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project builds on well documented, well supported and proven open source libraries such as &lt;a href=&quot;http://www.geotools.org/&quot;&gt;GeoTools&lt;/a&gt;, &lt;a href=&quot;http://openlayers.org/&quot;&gt;OpenLayers&lt;/a&gt;, &lt;a href=&quot;http://jquery.com/&quot;&gt;jQuery&lt;/a&gt; and &lt;a href=&quot;http://jqueryui.com/&quot;&gt;jQuery UI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We’re not quite there yet but you can follow the progress of the project through the &lt;a href=&quot;http://mineleni.github.io/CBSviewer/&quot;&gt;Github site&lt;/a&gt;&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/img/2013-04-12-screencapture.png&quot; alt=&quot;screen capture of the application&quot; /&gt;
  &lt;figcaption&gt;Rich client screen showing WOZ (property tax) values aggregrated to 100m blocks&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;a href=&quot;https://gispunt.wordpress.com/2013/04/12/cbsviewer-an-accessible-open-standards-based-viewer/&quot;&gt;This post was previously published&lt;/a&gt; on GISpunt.&lt;/p&gt;
</content>
        <category term="accessibility"/><category term="webmapping"/>
    </entry>

    <entry>
        <title>Performance and uptime monitoring Inspire View service</title>
        <link href="https://geodienstencentrum.github.io/blog/monitoring/performance/2011-09-06/performance-and-uptime-monitoring-inspire-view-service.html"/>
        <!-- <published>2003-12-13T09:17:51-08:00</published> -->
        <updated>2011-09-06T12:56:00+02:00</updated>
        <author>
            <name>GeoDienstenCentrum</name>
            <uri>https://geodienstencentrum.github.io/</uri>
            <email>mprins@users.sf.net</email>
        </author>
        <id>https://geodienstencentrum.github.io/blog/monitoring/performance/2011-09-06/performance-and-uptime-monitoring-inspire-view-service</id>
        <summary>Measuring uptime and performance of an Inspire view service using a round-robin database and python.</summary>
        <content type="html">&lt;p&gt;The &lt;a href=&quot;http://inspire.jrc.ec.europa.eu/&quot;&gt;Inspire directive&lt;/a&gt; has some fairly strict requirements regarding performance and uptime of services (QOS) (see: &lt;a href=&quot;http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=CELEX:32009R0976:EN:NOT&quot;&gt;32009R0976 Annex 1&lt;/a&gt; and the &lt;a href=&quot;http://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32010R1088&quot;&gt;amendment&lt;/a&gt;. Monitoring these parameters can easily be done using a few Python scripts and RRDtool. This provides an environment that is both lightweight and portable across platforms.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://oss.oetiker.ch/rrdtool/index.en.html&quot;&gt;RRDtool&lt;/a&gt; has been around for ages and is a de-facto instrument for lightweight logging systems gathering large amounts of data. The database   aggregates the input providing various algorithms such as average, max/min value as well as way more complex methods. The aggregation makes it possible to use the same database for years while the file size stays constant and the amount of information just keeps growing. Current versions of RRDtool provide Python bindings out of the box, however I chose to use  &lt;a href=&quot;http://pypi.python.org/pypi/PyRRD/&quot;&gt;PyRRD&lt;/a&gt; because I was unsuccessful compiling them using Visual Studio 10 first time around.&lt;/p&gt;

&lt;p&gt;I have chosen to monitor performance based on response time (the time needed for the initial byte to be received) and transfer time (the time needed for the last byte to be received).&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/img/2011-09-06-ehs-4h.png&quot; alt=&quot;graph showing 4h performance report&quot; /&gt;
  &lt;figcaption&gt;Performance measurements, note that responses also vary because of variations in
  requested image size&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;To prevent caching of the image a pseudo random bounding box and image size are used so that each request is unique, this generates some variance in the response size so the amount of data transferred (total bytes) for each request is also logged.&lt;/p&gt;

&lt;p&gt;Next to that uptime is monitored based on the correct mimetype of the GetMap response, the assumption here is that a mimetype other that requested means there was an error in the service, thus un-availability, this is a rather coarse approach, but it works for me because there is a separate error log that provides the details of a failure.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/img/2011-09-06-ehs-1w-down.png&quot; alt=&quot;graph showing 1 week downtime report&quot; /&gt;
  &lt;figcaption&gt;Any red line in this graph denotes a failure&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I have a batch file that runs the probe script every five minutes and create a graph every fifteen minutes, a HTML page is used to display the resulting graph as wel as provide access to the logfile and the last request.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://sourceforge.net/u/mprins/code/1/tree/viewserviceprobe/&quot;&gt;Browse or get the sourcecode.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://gispunt.wordpress.com/2011/09/06/performance-and-uptime-monitoring-inspire-view-service/&quot;&gt;This post was previously  published&lt;/a&gt; on GISpunt.&lt;/p&gt;
</content>
        <category term="monitoring"/><category term="performance"/>
    </entry>

    <entry>
        <title>GEOZET, Building a dual-mode GIS webapp</title>
        <link href="https://geodienstencentrum.github.io/blog/accessibility/webmapping/2010-07-06/geozet-building-a-dual-mode-gis-webapp.html"/>
        <!-- <published>2003-12-13T09:17:51-08:00</published> -->
        <updated>2010-07-06T15:53:00+02:00</updated>
        <author>
            <name>GeoDienstenCentrum</name>
            <uri>https://geodienstencentrum.github.io/</uri>
            <email>mprins@users.sf.net</email>
        </author>
        <id>https://geodienstencentrum.github.io/blog/accessibility/webmapping/2010-07-06/geozet-building-a-dual-mode-gis-webapp</id>
        <summary>Within the GEOZET viewer project an accessible GIS web viewer is being developed by Geonovum as one of the launching products of the PDOK programme.</summary>
        <content type="html">&lt;p&gt;Within the GEOZET viewer project a dual mode GIS web application is being developed by &lt;a href=&quot;https://www.geonovum.nl/&quot;&gt;Geonovum&lt;/a&gt; as one of the launching products of the &lt;a href=&quot;https://www.geonovum.nl/themas/pdok&quot;&gt;PDOK programme&lt;/a&gt;. Dual mode in this case being on the one hand a rich, map enabled client/GUI and on the other hand a lean non-javascript, non-css client/GUI for cases like screenreaders.
&lt;a href=&quot;http://www.osgis.nl/&quot;&gt;Bart&lt;/a&gt; has &lt;a href=&quot;http://osgisjs.blogspot.com/&quot;&gt;written&lt;/a&gt; about the OpenLayers based “rich” client in his posts, I’m working on the “core” version, that this post is about.&lt;/p&gt;

&lt;h2 id=&quot;application&quot;&gt;Application&lt;/h2&gt;

&lt;p&gt;GEOZET viewer is a web application that provides access to government publications (government in this case the local, provincial and state governments and associations) through a geographic means. Publications are documents such as building, cutting, liquor and other permits and licenses, press releases, legislation and so forth. It has been commissioned by ICTU and will serve as the “launching application” of the PDOK motor project.&lt;/p&gt;

&lt;h2 id=&quot;architecture-overview&quot;&gt;Architecture Overview&lt;/h2&gt;

&lt;p&gt;In a quick overview we have three open standards based webservices;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A tile service for the base map, only used in the rich client,&lt;/li&gt;
  &lt;li&gt;an OpenLS service for the Gazetteer/Geocoding that will probably run on the
    &lt;a href=&quot;http://www.kadaster.nl/web/artikel/productartikel/Adrescoordinaten-Nederland.htm&quot;&gt;Adres Coordinaten Nederland&lt;/a&gt; database&lt;/li&gt;
  &lt;li&gt;and a WFS service that has geocoded metadata about the publications; this includes
    address data and a hyperlink to the publication.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The WFS service is specific for this application, the former two are part of the &lt;a href=&quot;https://www.geonovum.nl/nieuws/pdok/update-van-stand-van-zaken-binnen-pdok&quot; data-proofer-ignore=&quot;true&quot;&gt;PDOK infrastucture&lt;/a&gt;. Because of some extra’s that we need (like returning area’s) we’ll probably be building our own Gazetteer using Hibernate Spatial and Lucene, more about this some other time.&lt;/p&gt;

&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;

&lt;p&gt;As part of this project I’ve been working on the WFS client that does the queries and renders the information based on user input. Two of the requirements to meet were easily transferable license(s) of the software stack between the hosting parties and platform independence. This boils down to using OpenSource toolkits on the Java platform. As most of the PDOK stack is based on &lt;a href=&quot;https://geoserver.org/&quot;&gt;Geoserver&lt;/a&gt; and &lt;a href=&quot;https://postgis.refractions.net/&quot;&gt;Postgis&lt;/a&gt; already our choice was easy, &lt;a href=&quot;https://geotools.org/&quot;&gt;GeoTools&lt;/a&gt;. It’s been quite a while since I’ve used GeoTools and a “first” look was quite overwhelming. I’ve opted to use the upcoming &lt;a href=&quot;https://docs.geotools.org/latest/userguide/welcome/upgrade.html#geotools-2-7&quot;&gt;2.7  release&lt;/a&gt; (which already has some milestones released) mainly because of the new, simplified Query and SimpleFeature objects that I need. This way implementing the WFS client, as a servlet, becomes a fairly straightforward exercise.&lt;/p&gt;

&lt;p&gt;The servlet essentially receives query input from the user though a simple HTML form, using either POST or GET, a radius and a location and optionally some filter categories. The user doesn’t actually see the location coordinate pair, just the placename they’ve entered and which has been sent to the Gazetteer for lookup.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/img/2010-07-06-geozet-core-screen.png&quot; alt=&quot;User input form for GEOZET viewer&quot; /&gt;
  &lt;figcaption&gt;This information is used to create a CQL filter to retrieve information.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Filter&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;maakFilter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xcoord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ycoord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;straal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;categorieen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ServletException&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

	&lt;span class=&quot;nc&quot;&gt;Filter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringBuilder&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filterString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;filterString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DWITHIN(&quot;&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getGeometryDescriptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getLocalName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;, POINT(&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xcoord&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ycoord&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;), &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;straal&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;, meters)&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;categorieen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;filterString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; AND (&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;categorieen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;filterString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FILTER_CATEGORIE_NAAM&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;=&apos;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;filterString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;categorieen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]);&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;filterString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&apos;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;categorieen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;n&quot;&gt;filterString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; OR &quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;filterString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CQL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toFilter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filterString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CQLException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;CQL Fout in de query voor de WFS.&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once we have the filter constructed we can fire off a query to the WFS and the result is parsed and rendered in a HTML list to the client. This way the information becomes accessible to screenreaders and other types of small capability” devices. In the parsing of the response I also calculate the distance between the objects in the response and the requested place so that the list can be sorted based on this distance, I’m using the UserData Map on the feature to store this information and then the sort method from the Collections framework.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SimpleFeature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ophalenBekendmakingen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Filter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xcoord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ycoord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Query&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setCoordinateSystem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CRS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EPSG:28992&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setTypeName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;typeName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setFilter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setPropertyNames&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ALL_NAMES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setHandle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GEOZET-handle&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NoSuchAuthorityCodeException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
				&lt;span class=&quot;s&quot;&gt;&quot;De gevraagde CRS autoriteit is niet gevonden.&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FactoryException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
				&lt;span class=&quot;s&quot;&gt;&quot;Gevraagde GeoTools factory voor CRS is niet gevonden.&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleFeatureCollection&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;features&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getFeatures&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;geometryFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createPoint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Coordinate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xcoord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;ycoord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;

	&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;afstand&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SimpleFeature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bekendmakingen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SimpleFeature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;();&lt;/span&gt;

	&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleFeatureIterator&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;features&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;features&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hasNext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleFeature&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feature&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;afstand&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Geometry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feature&lt;/span&gt;
					&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getDefaultGeometryProperty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;feature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getUserData&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;AFSTAND_NAAM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;afstand&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;bekendmakingen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;feature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;finally&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;nc&quot;&gt;Collections&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bekendmakingen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AfstandComparator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bekendmakingen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In a later stage we’ll probably also provide a “REST like” url, I’m still not sure how to do this though as the URL should be something “human” readable/understandable; we might end up just supporting the location information and not the filter as that makes things much simpler.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This project will go live on &lt;a href=&quot;https://www.overheid.nl/&quot;&gt;overheid.nl&lt;/a&gt; and be open sourced on the &lt;a href=&quot;http://www.osor.eu/&quot;&gt;Open Source Observatory and Repository&lt;/a&gt; (OSOR) November 1st, 2011.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;https://gispunt.wordpress.com/2010/07/06/geozet-building-a-dual-mode-gis-webapp/&quot;&gt;This post was previously  published&lt;/a&gt; on GISpunt.&lt;/p&gt;

</content>
        <category term="accessibility"/><category term="webmapping"/>
    </entry>

    <entry>
        <title>Testing your map service with JMeter</title>
        <link href="https://geodienstencentrum.github.io/blog/monitoring/performance/2009-09-22/testing-your-map-service-with-jmeter.html"/>
        <!-- <published>2003-12-13T09:17:51-08:00</published> -->
        <updated>2009-09-22T22:54:00+02:00</updated>
        <author>
            <name>GeoDienstenCentrum</name>
            <uri>https://geodienstencentrum.github.io/</uri>
            <email>mprins@users.sf.net</email>
        </author>
        <id>https://geodienstencentrum.github.io/blog/monitoring/performance/2009-09-22/testing-your-map-service-with-jmeter</id>
        <summary>Using Apache JMeter and some random address data we can run performance tests against a mapservice.</summary>
        <content type="html">&lt;p&gt;&lt;a href=&quot;http://jmeter.apache.org/&quot; title=&quot;JMeter website&quot;&gt;Apache JMeter&lt;/a&gt; is a powerful tool for load testing functional behaviour and performance of applications over the network. It is however not the most accessible or easy to use tool, mostly because of the overwhelming amount of options. Once started though there is no stopping! We use JMeter primarily to load test our GIS web applications (eg. &lt;a href=&quot;http://epractice.eu/cases/eBRPeGDI&quot; title=&quot;eBRP summary&quot;&gt;eBRP&lt;/a&gt;) so that we can see if these scale to the sometimes huge amount of concurrent users, in these scenarios we test a web application as a whole, however as we move into a more service oriented architecture we feel a need to test at a smaller scale, ie. the service level. Since many of our map services are exposed with a REST endpoint this is the easiest place to attach our test to.&lt;/p&gt;

&lt;p&gt;A common way of working with JMeter is to record one or more typical sessions using the JMeter  built-in proxy and recording function, these are then edited so they can be parametrized with user credential and session information. When starting a recording session you must start off with a simple scenario, if you don’t you’ll just get lost in the amount of information that is recorded.&lt;/p&gt;

&lt;p&gt;For testing our mapservice we can basically follow the same procedure; using the ArcGIS server built-in JavaScript viewer or a simple test application we can record a user session. The result is then (in this case) parametrized so we can look at random locations on the map and do identify operations at random locations., to initially go to a random location we have a list of 100 address locations (zip;number;x coordinate;y coordinate) in a .csv file that have been randomly drawn from our address database. Then we put in some elements called &lt;a href=&quot;http://jmeter.apache.org/usermanual/component_reference.html#BSF_PreProcessor&quot; title=&quot;BSF PreProcessor docs&quot;&gt;BSF PreProcessors&lt;/a&gt; that will do some simple calculus in JavaScript to determine bounding boxes and such as shown below.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// retrieve wkid and bboxSize&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;wkid&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;wkid&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bboxSize&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseFloat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;bboxSize&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// randomize zoomfactor, bboxSize&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;randomnumber&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;zM&lt;/span&gt;           &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;randomnumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bboxSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// resize bbox&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xmin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseFloat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;xmin&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;zM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xmax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseFloat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;xmax&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;zM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ymin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseFloat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ymin&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;zM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ymax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseFloat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ymax&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;zM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// store in memory&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;xmin&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;xmax&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xmax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ymin&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ymin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ymax&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ymax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;bbox&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;{&quot;xmin&quot;:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xmin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;,&quot;ymin&quot;:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ymin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;,&quot;xmax&quot;:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xmax&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;,&quot;ymax&quot;:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ymax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;,&quot;spatialReference&quot;:{&quot;wkid&quot;:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;wkid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;bbox updater zoom in: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;bbox&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next up is adding some expectations that we want to be fulfilled, eg. we want to have all responses a HTTP status code of 200 (which means OK), we want image request to have the proper mime type (ie. a png8 image should be returned with ContentType: image/png and we are expecting certain response times). These are set up by adding &lt;a href=&quot;http://jmeter.apache.org/usermanual/component_reference.html#Response_Assertion&quot; title=&quot;Response Assertion docs&quot;&gt;Response Assertions&lt;/a&gt; to our JMeter script.&lt;/p&gt;

&lt;p&gt;Now we can add some advanced options such as &lt;a href=&quot;http://jmeter.apache.org/usermanual/component_reference.html#logic_controllers&quot; title=&quot;Logic Controllers docs&quot;&gt;Logic Controllers&lt;/a&gt; and &lt;a href=&quot;http://jmeter.apache.org/usermanual/component_reference.html#timers&quot; title=&quot;Timers docs&quot;&gt;Timers&lt;/a&gt; to further randomize the load and number of sessions to our service. And finally we want to have our results so we add in some &lt;a href=&quot;http://jmeter.apache.org/usermanual/component_reference.html#listeners&quot; title=&quot;Listeners docs&quot;&gt;Listeners&lt;/a&gt; such as graphs and tables. These Listeners can also be used to export the test results to an XML or CSV formatted file or an image.&lt;/p&gt;

&lt;h2 id=&quot;get-going&quot;&gt;Get going&lt;/h2&gt;
&lt;p&gt;So get started, &lt;a href=&quot;https://jmeter.apache.org/download_jmeter.cgi&quot; title=&quot;JMeter download location&quot;&gt;download JMeter&lt;/a&gt; and load the script (.jmx) attached to this post. Get a list of point data in a csv file (the attached .csv is in Rijksdriehoek / EPSG:28992 which may or may not be useful to you), when you use your own you may need to tweak the format in the “CSV Data Set Config - adressen”, also you probably also need to tweak some of the JavaScript code in the preprocessors as these are based on a regular grid in meters. I guess if your data is in UTM you should be fine.&lt;/p&gt;

&lt;p&gt;You need to specify/adapt the parameters in the test plan (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;users&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iteraties&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mapPath&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gisHost&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gisPort&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wkid&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fullExtent&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zoomExtent&lt;/code&gt;) to suit your mapservice. To start off choose a small number for both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;users&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iteraties&lt;/code&gt; such as 1. You should now be ready to go…&lt;/p&gt;

&lt;p&gt;Download &lt;a href=&quot;/img/2009-09-22-jmeter_script.zip&quot;&gt;JMeter script .zip&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;interpret-results&quot;&gt;Interpret Results&lt;/h2&gt;
&lt;p&gt;JMeter really doesn’t know what you’re using it for, so interpreting results is sometime a challenge in itself. There are some Timeout parameters (assertions) that you can adjust to specify minimum thresholds for response times and there’s a large number of &lt;a href=&quot;http://jmeter.apache.org/usermanual/component_reference.html#listeners&quot; title=&quot;Listeners docs&quot;&gt;Listeners&lt;/a&gt; that will help you visualize the results or export them to something like CSV which you can then use in you favourite spreadsheet or reporting tool.&lt;/p&gt;

&lt;h2 id=&quot;a-sample-run&quot;&gt;A sample Run&lt;/h2&gt;
&lt;p&gt;Using the posted .jmx I ran a test on one of our development test servers, these are virtualized dual cpu win2003 systems running on esx; they are not production grade systems. Below you can see some of the results of an optimized mapservice (.msd) containing an aerial photograph of the Netherlands stored in a 24x7 oracle10 database from our production environment. I have set up the testplan to use 50 users with 10 iterations each and a rampup time of 900 seconds using only the map requests (not the identify); JMeter unfortunately didn’t quite make it to the end of the test due to a memory errror, so this needs to be tweaked a bit in the startup script of JMeter; it’s likely the result of all the listeners in the .jmx so you may want to disable one or two of them.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/img/2009-09-22-responseresult.jpg&quot; alt=&quot;response result screen capture&quot; /&gt;
  &lt;figcaption&gt;Typical response result for a map image&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;In the results tree shown in the first screen capture I have only logged the errors; these are erroneous because the response took too long to load (more/longer than the &lt;em&gt;mapRequestResponseTimeMillis&lt;/em&gt; set at 950 ms).&lt;/p&gt;

&lt;p&gt;In the second screen capture you can see the aggregate results of the testrun, which clearly shows that it takes longer to get a more detailed part of the map from the database.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/img/2009-09-22-aggregare_response_time.jpg&quot; alt=&quot;Aggregate reponse time graph&quot; /&gt;
  &lt;figcaption&gt;Aggregate reponse time graph&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
  &lt;img src=&quot;/img/2009-09-22-perfmon.jpg&quot; alt=&quot;perfmon graph from the AGS server during the test&quot; /&gt;
  &lt;figcaption&gt;perfmon graph from the AGS server during the test&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The test is incomplete without also monitoring the server. There are a number of built-in tools for windows, such as Perfmon and of course the taskmanager.In my set up I noticed a competition between the two SOC processes running the map and the Java process running the servlet engine that runs the REST interface, each of the managed to get up to 1/3 of the total available CPU.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/img/2009-09-22-cpu.jpg&quot; alt=&quot;CPU utilization graph during test&quot; /&gt;
  &lt;figcaption&gt;CPU (green) and memory (yellow) utilization graph during test&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;ArcGIS Manager also provides some graphs showing throughput.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/img/2009-09-22-throughput_by_service.png&quot; alt=&quot;Throughput from the AGS manager console&quot; /&gt;
  &lt;figcaption&gt;Throughput graph from the AGS manager console&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;a href=&quot;https://gispunt.wordpress.com/2009/09/22/testing-your-map-service-with-jmeter/&quot;&gt;This post was previously published&lt;/a&gt; on GISpunt.&lt;/p&gt;
</content>
        <category term="monitoring"/><category term="performance"/>
    </entry>


</feed>
