EurActiv Map API


Log in to deploy new versions or manage existing ones.


EurActiv Network

Purpose of the Map API

The EurActiv Map API exists to provide EurActiv and its partners with a "write-once, use-everywhere" map for use in its websites. Please note that although this API has no technical use restrictions, it is covered by all applicable copyright and trademark law. Explicit consent of EurActiv PLC is required for its use.

Load the Map API

<script src='//assets.euractiv.com/eamap/v3/eamap-min.js'></script>

Using the Map API

A number of examples on how to use the Map API are outlined below. If you're just looking for a quick start, copy the code from the "Complete Example" below and modify to your needs.

Warning: while the API itself is stable, default settings (eg, the size of the map, the colors, etc) are not. It is therefore recommended that you set these defaults explicitly, as is done in the "Complete Example" tab below.

Documentation and Examples


This is the simpliest possible example of the map. Let's take a look at what is happening.

First, load the map script:

<script src="//assets.euractiv.com/eamap/v1/eamap.min.js"></script>

Please note that this script has a number of dependencies:

  • jQuery version 1.11 (will probably work from v1.4, not tested)
  • Google JSAPI
  • Google Feeds API
  • Raphaeljs version 2.x (includes 2.1.3 by default)

These dependencies will be automatically loaded if they are not present. If you need to use any of your own versions of the above libraries, be sure to include them above this script.

Then, construct a new instance of the map:

eamap = new EaMap();

The map instance needs at a minimum two pieces of information: where to draw the map and where to draw the RSS feed. The next two lines achieve this:

eamap.setMapContainer('#basic .map');
eamap.setRssContainer('#basic .rss');

Both of these functions accept either a CSS selector (string) or a DOM object. They can be anywhere on the page, but for the sake of UX they should be as close together as possible.

The final thing to do is to tell the map instance that we are done configuring it and that it can draw itself:

eamap.dispatch();

The dispatch method can be called any time, but the actual render will be deferred until after all dependencies have loaded and the page DOM is ready. Once a map is dispateched, it will not accept any further configuration changes (ie, you can no longer move it or change its colors, etc).

<script>(function () {
    eamap = new EaMap();
    eamap.setMapContainer('#basic .map');
    eamap.setRssContainer('#basic .rss');
    eamap.dispatch();
}());</script>

<table id="basic"><tr>
    <td class="map"></td>
    <td class="rss"></td>
</tr></table>

Under some circumstances (eg, touch screens) it is useful to have a pure html menu in addition to the roll-over map. By calling setMenuContainer, the EaMap object will build a list of menu items inside of the specified container element. When elements of the menu are moused over, they will trigger a mouseover event on the related map element.

By default, the menu items will simply be anchor elements wrapped in a list item element, thus: <li><a href="[url]">[title]</a></li>. However, the setMenuFormatter method allows you to pass any formatting function you wish. The formatting function should accept two string arguments: href and text. These arguments have already been html-escaped and should be safe to concatenate directly into HTML. The formatter function should return either a string of HTML or a DOM object (not a jQuery object).

<script>(function () {
    eamap = new EaMap();
    eamap.setMapContainer('#selector .map');
    eamap.setRssContainer('#selector .rss');
    eamap.setMenuContainer('#selector .menu-ul');
    var zebra = false;
    eamap.setMenuFormatter(function (href, text) {
        var bgc = zebra ? '#fff' : '#ddd';
        zebra = !zebra;
        return '<li><a style="background-color:' + bgc + '" href="' + href + '">' + text + '</a></li>';
    });
    eamap.dispatch();
}());</script>

<table id="selector"><tr>
    <td class="menu">
        <ul class="nav nav-pills">
        <li class="dropdown">
            <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                Country Selector <span class="caret"></span>
            </a>
            <ul class="dropdown-menu menu-ul"></ul>
        </li>
    </ul></td>
    <td class="map"></td>
    <td class="rss"></td>
</tr></table>



Responsive and design mostly falls outside of the scope of this library and should be handled by whichever design framework you are using. However, the map object does perform a couple of checks to see if it is in a responsive or mobile environment that should help integration.

Mobile: A "Mobile" design is one that sends a subset of the html to mobile phones so that a page looks right on mobile devices. In this case, the RSS feed may not be present, but the map may be. In this case, simply omit the call to setRssContainer and the RSS capabilities will not be added.

Responsive: A "Responsive" design uses CSS media queries to show or hide various elements in response to the device width. In this case, you can build the EaMap object as usual, but use your frontend framework (Bootstrap, in this case) to show or hide the RSS feed as desired. The EaMap object will only load the RSS if the feed area is shown, so the resource-use on mobile devices will remain minimal.

<style>
    #responsive ul {
        padding-left:0;
        list-style-type:none;
        position:relative;
    }
    #responsive li {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

</style>

<script>(function () {
    eamap = new EaMap();
    eamap.setMapContainer('#mobile');
    eamap.dispatch();
}());</script>

<div id="mobile"></div>

<script>(function () {
    eamap = new EaMap();
    eamap.setMapContainer('#responsive .map');
    eamap.setRssContainer('#responsive .rss');
    eamap.dispatch();
}());</script>

<div id="responsive" class="row">
    <div class="map col-xs-12 col-sm-5 col-md-4 col-lg-3"></div>
    <div class="rss hidden-xs col-sm-7 col-md-8 col-lg-9"></div>
</div>



The map has an aspect ratio of 16x9 and will scale up indefinitely. To set the map size, use the setZoom method. It takes one argument, the zoom factor, which is multiplied by 16 and 9 to get the map width and height, respectively.

The map does not support cropping natively, which should be acheived by placing the map inside of a properly sized wrapper.

Note: The SVG coordinates that underlay the map are a bit off and will look wrong when scaled up significantly. We hope to fix this error in a future version.

<script>(function () {
    eamap = new EaMap();
    eamap.setMapContainer('#size-large');
    eamap.setZoom(20);
    eamap.dispatch();
}());</script>
<div id="size-large"></div>


<script>(function () {
    eamap = new EaMap();
    eamap.setMapContainer('#size-small');
    eamap.setZoom(10);
    eamap.dispatch();
}());</script>
<div id="size-small"></div>

<style>
    #size-crop {
        height: 100px;
        overflow: hidden;
        position:relative;
    }
    #size-crop > * {
        position:relative;
        top:-50px;
    }
    
</style>
<script>(function () {
    eamap = new EaMap();
    eamap.setMapContainer('#size-crop');
    eamap.dispatch();
}());</script>
<div id="size-crop"></div>



Colors and other styles are controlled in three ways:

  • setBranding sets the styling that applies to countries on the map in function of their relationship to the EurActiv brand. Possible properties:
    • highlight: the country is moused over or selected
    • ea_core: a country of the core EurActiv network
    • ea_network: a country of the EurActiv network
    • ea_syndicated: a country with a syndication partner
    • eu: an eu-member state with no EurActiv presence
    • noneu: a non-eu European country with no Euractiv presence
    • other: a country outside of Europe, no EurActiv presence
    Note that although this example uses colornames for clarity, hexadecimal color codes are preferable (eg, #ffffff).
  • setStyle sets styling for the SVG object (eg, the map itself). This method should be used sparingly in favor of CSS where possible. However, for cross-browser compatability, it is best to set the following properties using this method:
    • fill-opacity: 0 (transparent) to 1 (opaque)
    • stroke: a hexdec color or html color name, sets the color of the lines around countries.
    • stroke-width: integer, sets width of lines around countries.
    • stroke-opacity: 0 (transparent) to 1 (opaque)
  • CSS: all other styling (of the RSS feed area, etc) should be handled in CSS.
<style>
    #branding td {
        padding:10px;
        vertical-align:top;
    }
    #branding ul {
        padding: 5px 0;
        list-style-type: none;
    }
    #branding li {
        padding-bottom: 5px;
    }
</style>

<script>(function () {
    eamap = new EaMap();
    eamap.setMapContainer('#branding .map');
    eamap.setRssContainer('#branding .rss');
    eamap.setBranding({
        highlight: 'red',
        ea_core: 'darkorange',
        ea_network: 'orange',
        ea_syndicated: 'yellow',
        eu: 'navy',
        noneu: 'blue',
        other: 'gray'
    });
    eamap.setStyle({
        'fill-opacity': '0.5',
        stroke: 'green',
        'stroke-width': '5',
        'stroke-opacity': '1'
    });
    eamap.dispatch();
}());</script>

<table id="branding"><tr>
    <td class="map"></td>
    <td class="rss"></td>
</tr></table>

To set the number of entries in the RSS feed area, use the rssCount method. The method accepts any positive integer.

<script>(function () {
    eamap = new EaMap();
    eamap.setMapContainer('#rsscount .map');
    eamap.setRssContainer('#rsscount .rss');
    eamap.setRssCount(2);
    eamap.dispatch();
}());</script>

<table id="rsscount"><tr>
    <td class="map"></td>
    <td class="rss"></td>
</tr></table>

Country flags

Country flags are a visual way to remind the user of the size of the EurActiv network and are best rendered far from the map (eg, in the page footer). To insert the flags, use the setFlagContainers method. This method expects an object in which the keys are one of the three levels of participation in the EurActiv network (core, network, syndicated) and the values are the elements in which to insert the flags (see example).

To control the way that the markup renders, you can use the setFlagFormatter method. It expects a single argument: the formatter callback function. The formatter should return either a string of HTML or a DOM object. It should accept four parameters:

  • href the network partner's homepage URL
  • base_url the base url of the flag image directory
  • code the two letter country code of the partner
  • title the name of the network partner

The default flag icons are flat jpgs of the countries. In general, these images are sufficient and can be styled with CSS to provide effects like drop shadows, rounded corners or gloss. Nevertheless, to use a custom icon set you can set the base url with the method setFlagBaseUrl. Note that you will probably also have to implement a custom formatter to properly display the images.

<style>
  #flags td:last-child {
    text-align:center;
  }
  #flags td:last-child a {
    display:inline-block;
    padding:5px;
  }
  #flags td:last-child a img {
    display:block;
  }
  
</style>


<script>(function () {
    eamap = new EaMap()
        .setMapContainer('#flags .map')
        .setFlagContainers({
            core: '#flags .flags-core',
            network: '#flags .flags-network',
            syndicated: '#flags .flags-syndicated'
        })
        .dispatch();
}());</script>

<table id="flags">
    <tr>
        <td rowspan="3" class="map"></td>
        <td class="flags-core">
    </tr>
    <tr><td class="flags-network"></tr>
    <tr><td class="flags-syndicated"></tr>
</table>



You may need to fire events after the map is fully loaded. In this example, the map.rand method is only available after the map loads and calling it earlier will throw an error. To set an onload callback, use the setCallback method. It accepts one argument, the onload callback function.

Warning The setCallback method will overwrite (eg, delete) any previously set callbacks.

Note The map.rand method is part of the map object's internal workings and not the public API. It is used here as an example, but it can change at any time and without warning.

<script>(function () {
    eamap = new EaMap();
    eamap.setMapContainer('#callback .map');
    eamap.setRssContainer('#callback .rss');
    var local = eamap;
    eamap.setCallback(function () {
        setInterval(function () {
            local.map.rand();
        }, 1000);
    });
    eamap.dispatch();
}());</script>

<table id="callback"><tr>
    <td class="map"></td>
    <td class="rss"></td>
</tr></table>

You can customize the "Loading..." string that displays while the RSS feeds load using the EaMap.setRssTransition method.

It accepts a single string, the markup to place in the RSS box while the feed loads.

<script>(function () {
    eamap = new EaMap();
    eamap.setMapContainer('#transition .map');
    eamap.setRssContainer('#transition .rss');
    var local = eamap;
    eamap.setRssTransition('My custom string');
    eamap.dispatch();
}());</script>

<table id="transition"><tr>
    <td class="map"></td>
    <td class="rss"></td>
</tr></table>

A complete example of the map.

EurActiv Network
<style>
    #complete .selector-stripe {
        background-color:#0c285d;
    }
    #complete .dropdown > a {
        color:white;
    }
    #complete .dropdown:hover > a,
    #complete .dropdown.open > a {
        color:black;
    }

    #complete .map-stripe {
        background-color: #fee300;
        font-family: 'Open Sans', Arial, Helvetica, 'Nimbus Sans L', sans-serif
    }
    
    #complete .img {
        padding: 20px 0;
        text-align: center;
    }
    
    #complete .map {
        overflow:hidden;
        text-align:center;
    }
    
    #complete .rss {
        padding-top: 20px;
    }
    #complete .rss a {
        color:#014ba3;
    }
    #complete .rss ul {
        padding-left:0;
        list-style-type:none;
        position:relative;
    }
    #complete .rss li {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        font-size:13px;
        font-style: italic;
    }
    #complete .flag-stripe {
        background-color:#122742;
        text-align:center;
        font-size: 14px;
    }
    #complete .flag-stripe div {
      min-height: 75px;
      vertical-align:center;
    }
    #complete .flag-stripe a, #complete .flag-title span {
        color:white;
        display:inline-block;
        padding: 15px 5px 5px;
        vertical-align:middle;
    }
    #complete .flag-stripe a img {
        display:block;
    }
    #complete .flag-title {
      font-weight:bold;
      font-size: 18px;
    }
    #complete .flags-network {
      background-color: #15387c;
    }
    #complete .flags-syndicated {
      background-color: #2f62b7
    }
</style>

<script>(function () {
    eamap = new EaMap()
        .setMapContainer('#complete .map')
        .setRssContainer('#complete .rss')
        .setMenuContainer('#complete .menu')
        .setFlagContainers({
            core: '#complete .flags-core',
            network: '#complete .flags-network',
            syndicated: '#complete .flags-syndicated'
        })
        .setZoom(14)
        .setBranding({
            highlight: '#f7d25c',
            ea_core: '#4e82bd',
            ea_network: '#809cd0',
            ea_syndicated: '#d9e4f1',
            eu: '#fee300',
            noneu: '#fee300',
            other: '#fee300'
        })
        .setStyle({
            'fill-opacity': '1',
            stroke: '#ffffff',
            'stroke-width': '4',
            'stroke-opacity': '1'
        })
        .setRssCount(3)
        .dispatch();
}());</script>

<div id="complete">
    <div class="row selector-stripe clearfix">
        <ul class="nav nav-pills pull-right">
            <li class="dropdown">
                <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                    EurActiv Network <span class="caret"></span>
                </a>
                <ul class="dropdown-menu menu"></ul>
            </li>
        </ul>
    </div>
    <div class="row map-stripe">
        <div class="img col-xs-4 col-sm-3 col-md-2 col-lg-2">
            <img src="./logo.png">
        </div>
        <div class="map col-xs-8 col-sm-3 col-md-3 col-lg-3"></div>
        <div class="rss hidden-xs col-sm-6 col-md-7 col-lg-7"></div>
    </div>
    <div class="row flag-stripe">
        <div class="col-lg-1 col-md-12 col-sm-12 flag-title"><span>EurActiv Network</span></div>
			  <div class="col-lg-3 col-md-4 col-sm-6 flags-core"></div>
			  <div class="col-lg-3 col-md-3 col-sm-6 flags-network"></div>
			  <div class="col-lg-5 col-md-5 col-sm-12 flags-syndicated"></div>
    </div>
</div>


Roadmap

Some changes planned for future versions:

Configuration

Configuration is located in the file /config/eamap.php. If you do not have the ability to modify this file, contact your administrator to have options changed. The configuration file should contain an array with the name $config containing the following offsets:

NameTypeDescriptionCurrent Setting
callmap_driverstringThe callmap driver to use, either "sqlite", "fsstore" or "noop"
noop
callmap_labelsarrayLabels for the callmap, where the key is the regular expression to match and the value is the label to useLogin to view this setting
callmap_visualize_defaultarrayNodes to visualize by defaultLogin to view this setting
callmap_probabilityintegerProbability that a given hit will log. Important for high traffic sites. Set higher for lower probability.
1000
http_allowed_domainsarrayAllowed domains for fetching assets or generating URLsLogin to view this setting
http_allowed_urlsarraySpecified URLs or regular expressions of specified URLs match for fetching assets or generating URLsLogin to view this setting
http_connect_timeoutintegerThe amount of time, in seconds, that cURL should wait before returning an error status. 15 is a good value for most cases.
15
error_driverstringThe driver to use for error logging, one of "noop" or "sqlite"
noop

Error [E_WARNING]: Unknown: open(/var/lib/php5/sessions/sess_1l7peuaolq392vfr32h17c7vq6, O_RDWR) failed: Disk quota exceeded (122) (Unknown:0)
Error [E_WARNING]: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/var/lib/php5/sessions) (Unknown:0)