'),
+ metric = $$('.userCountryMapSelectMetrics').val(),
+ v = formatNumber(Math.round(val), metric, first);
+
+ d.css({ width: 17, height: 17, float: 'left', background: colscale(val) });
+ l.css({ 'margin-left': 20, 'line-height': '20px', 'text-align': 'right' }).html(v);
+ r.css({ clear: 'both', height: 19 });
+ r.append(d).append(l);
+ $('.UserCountryMap-legend .content').append(r);
+ }
+
+ var stats, values = [], id = self.lastSelected, c, showLegend;
+
+ $.each(rows, function (i, r) {
+ if (!$.isFunction(filter) || filter(r)) {
+ var v = quantify(r, metric);
+ if (!isNaN(v)) values.push(v);
+ }
+ });
+
+ stats = minmax(values);
+ showLegend = values.length > 0;
+
+ if (stats.min == stats.max) {
+ colscale = function () { return chroma.hex(oneCountryColor); };
+ if (choropleth) {
+ $('.UserCountryMap-legend .content').html('').show();
+ if (showLegend) {
+ addLegendItem(stats.min, true);
+ }
+ }
+ return colscale;
+ }
+
+ colscale = chroma.scale()
+ .range([choropleth ? colorRangeStartChoropleth : colorRangeStartNormal,
+ choropleth ? colorRangeEndChoropleth : colorRangeEndNormal])
+ .domain(values, 4, 'c')
+ .mode('lch');
+
+ if (metric == 'avg_time_on_site' || metric == 'nb_actions_per_visit' || metric == 'bounce_rate') {
+ if (id.length == 3) {
+ c = (stats.p90 - stats.min) / (stats.max - stats.min);
+ colscale = chroma.scale(specialMetricsColorScale, [0, c, c + 0.001, 1])
+ .domain(chroma.limits(rows, 'c', 5, 'curMetric', filter), 4, 'c')
+ .mode('hsl');
+ }
+ }
+
+ // a good place to update the legend, isn't it?
+ if (choropleth && showLegend) {
+ $('.UserCountryMap-legend .content').html('').show();
+ var itemExists = {};
+ $.each(chroma.limits(values, 'k', 3), function (i, v) {
+ if (itemExists[v]) return;
+ addLegendItem(v, i === 0);
+ itemExists[v] = true;
+ });
+
+ } else {
+ $('.UserCountryMap-legend .content').hide();
+ }
+
+ return colscale;
+ }
+
+ function formatPercentage(val) {
+ if (val < 0.001) {
+ return '< ' + NumberFormatter.formatPercent(0.1);
+ }
+ return NumberFormatter.formatPercent(Math.round(1000 * val) / 10);
+ }
+
+ /*
+ * to ensure that onResize is not called a hundred times
+ * while resizing the browser window, this functions
+ * makes sure to only call onResize at the end
+ */
+ function onResizeLazy() {
+ clearTimeout(self._resizeTimer);
+ self._resizeTimer = setTimeout(self.resize.bind(self), 300);
+ }
+ // Save a reference to the function so it can be cleanly removed
+ // as a listener later.
+ self._onResizeLazy = onResizeLazy;
+
+ function activateButton(btn) {
+ $$('.UserCountryMap-view-mode-buttons a').removeClass('activeIcon');
+ btn.addClass('activeIcon');
+ $$('.UserCountryMap-activeItem').offset({ left: btn.offset().left });
+ }
+
+ function initUserInterface() {
+ // react to changes of country select
+ $$('.userCountryMapSelectCountry').off('change').change(function () {
+ hasUserZoomed = true;
+ updateState($$('.userCountryMapSelectCountry').val());
+ });
+
+ function zoomOut() {
+ hasUserZoomed = true;
+ var t = self.lastSelected,
+ tgt = 'world'; // zoom out to world per default..
+ if (t.length == 3 && UserCountryMap.ISO3toCONT[t] !== undefined) {
+ tgt = UserCountryMap.ISO3toCONT[t]; // ..but zoom to continent if we know it
+ }
+ updateState(tgt);
+ }
+
+ // enable zoom-out
+ $$('.UserCountryMap-btn-zoom').off('click').click(zoomOut);
+ $$('.UserCountryMap_map').off('click').click(zoomOut);
+
+ // handle window resizes
+ $(window).resize(onResizeLazy);
+
+ // enable metric changes
+ $$('.userCountryMapSelectMetrics').off('change').change(function () {
+ updateState(self.lastSelected);
+ });
+
+ // handle city button
+ (function (btn) {
+ btn.off('click').click(function () {
+ if (self.lastSelected.length == 3) {
+ if (self.mode != "city") {
+ self.mode = "city";
+ hasUserZoomed = true;
+ updateState(self.lastSelected);
+ }
+ }
+ });
+ })($$('.UserCountryMap-btn-city'));
+
+ // handle region button
+ (function (btn) {
+ btn.off('click').click(function () {
+ if (self.mode != "region") {
+ $$('.UserCountryMap-view-mode-buttons a').removeClass('activeIcon');
+ self.mode = "region";
+ hasUserZoomed = true;
+ updateState(self.lastSelected);
+ }
+ });
+ })($$('.UserCountryMap-btn-region'));
+
+ // add loading indicator overlay
+
+ var bl = $('
');
+ bl.hide();
+ $$('.UserCountryMap_map').append(bl);
+
+ var infobtn = $('.UserCountryMap-info-btn');
+ infobtn.off('mouseenter').on('mouseenter',function (e) {
+ $(infobtn.data('tooltip-target')).show();
+ }).off('mouseleave').on('mouseleave', function (e) {
+ $(infobtn.data('tooltip-target')).hide();
+ });
+ $('.UserCountryMap-tooltip').hide();
+ }
+
+ /*
+ * updateState, called whenever the view changes
+ */
+ function updateState(id) {
+ // double check view mode
+ if (self.mode == "city" && id.length != 3) {
+ // city mode is reserved for country views
+ self.mode = "region";
+ }
+
+ var metric = $$('.userCountryMapSelectMetrics').val();
+ // store current map state
+ self.widget.dashboardWidget('setParameters', {
+ lastMap: id, viewMode: self.mode, lastMetric: metric
+ });
+
+ $('.UserCountryMap-info-btn').hide();
+
+ try {
+ // check which map to render
+ if (id.length == 3) {
+ // country map
+ renderCountryMap(id, metric);
+ } else {
+ // world or continent map
+ renderWorldMap(id, metric);
+ }
+
+ } catch (e) {
+ // console.error(e);
+ $('.UserCountryMap-info .content').html(e);
+ $('.UserCountryMap-info').show();
+ }
+
+ _updateUI(id, metric);
+
+ self.lastSelected = id;
+ }
+
+ /*
+ * update the widgets ui according to the currently selected view
+ */
+ function _updateUI(id, metric) {
+ // update UI
+ if (self.mode == "city") {
+ activateButton($$('.UserCountryMap-btn-city'));
+ } else {
+ activateButton($$('.UserCountryMap-btn-region'));
+ }
+ var countrySelect = $$('.userCountryMapSelectCountry');
+ countrySelect.val(id);
+
+ var zoom = $$('.UserCountryMap-btn-zoom');
+ if (id == 'world') zoom.addClass('inactiveIcon');
+ else zoom.removeClass('inactiveIcon');
+
+ // show flag icon in select box
+ var flag = $$('.userCountryMapFlag'),
+ regionBtn = $$('.UserCountryMap-btn-region');
+ if (id.length == 3) {
+ if (UserCountryMap.countriesByIso[id]) { // we have visits in this country
+ flag.css({
+ 'background-image': 'url(' + UserCountryMap.countriesByIso[id].flag + ')',
+ 'background-repeat': 'no-repeat',
+ 'background-position': '5px 5px'
+ });
+ $$('.UserCountryMap-btn-city').removeClass('inactiveIcon').show();
+ $('span', regionBtn).html(regionBtn.data('region'));
+ } else {
+ // not a single visit in this country
+ $$('.UserCountryMap-btn-city').addClass('inactiveIcon');
+ $('.map-stats').html(_.no_data);
+ $('.map-title').html('');
+ return;
+ }
+
+ } else {
+ flag.css({
+ 'background': 'none'
+ });
+ $$('.UserCountryMap-btn-city').addClass('inactiveIcon').hide();
+ $('span', regionBtn).html(regionBtn.data('country'));
+ }
+
+ var mapTitle = id.length == 3 ?
+ UserCountryMap.countriesByIso[id].name :
+ $$('.userCountryMapSelectCountry option[value=' + id + ']').html(),
+ totalVisits = 0,
+ totalMetricValue = 0;
+ // update map title
+ $('.map-title').html(mapTitle);
+ $$('.widgetUserCountryMapvisitorMap .widgetName .map-title').html(' – ' + mapTitle);
+ // update total visits for that region
+ if (id.length == 3) {
+ totalVisits = UserCountryMap.countriesByIso[id]['nb_visits'];
+ totalMetricValue = UserCountryMap.countriesByIso[id][metric];
+ } else if (id.length == 2) {
+ $.each(UserCountryMap.countriesByIso, function (iso, country) {
+ if (UserCountryMap.ISO3toCONT[iso] == id) {
+ totalVisits += country['nb_visits'];
+ totalMetricValue += country[metric];
+ }
+ });
+ } else {
+ totalVisits = self.config.visitsSummary['nb_visits'];
+ totalMetricValue = self.config.visitsSummary[metric];
+ }
+
+ var data = {};
+ data[metric] = totalMetricValue;
+ $('.map-stats').html(
+ '
' + formatValueForTooltips(data, metric, false) + ' ' +
+ (id != 'world' ? (' (' + formatPercentage(totalMetricValue / self.config.visitsSummary[metric]) + ')') : '')
+ );
+ }
+
+ /*
+ * called by updateState if either the world or a continent is selected
+ */
+ function renderWorldMap(target, metric) {
+
+ /**
+ * update the colors of the countrys
+ */
+ function updateColorsAndTooltips(metric) {
+
+ // Create a chroma ColorScale for the selected metric that regards only the
+ // countries that are visible in the map.
+ colscale = getColorScale(UserCountryMap.countryData, metric, function (r) {
+ if (target.length == 2) {
+ return UserCountryMap.ISO3toCONT[r.iso] == target;
+ } else {
+ return true;
+ }
+ }, true);
+
+ function countryFill(data) {
+ var d = UserCountryMap.countriesByIso[data.iso];
+ if (d === null) {
+ return self.config.noDataColor;
+ } else {
+ return colscale(d[metric]);
+ }
+ }
+
+ var countryLayer = map.getLayer('countries');
+ if(countryLayer) {
+ // Apply the color scale to the map.
+ countryLayer
+ .style('fill', countryFill)
+ .on('mouseenter', function (d, path, evt) {
+ if (evt.shiftKey) { // highlight on mouseover with shift pressed
+ path.attr('fill', countryHighlightColor);
+ }
+ })
+ .on('mouseleave', function (d, path, evt) {
+ if ($.inArray(UserCountryMap.countriesByIso[d.iso].name, _rowEvolution.labels) == -1) {
+ path.attr('fill', countryFill(d)); // reset color
+ }
+ });
+
+ // Update the map tooltips.
+ countryLayer.tooltips(function (data) {
+ var metric = $$('.userCountryMapSelectMetrics').val(),
+ country = UserCountryMap.countriesByIso[data.iso];
+ return '
' + country.name + ' ' +
+ formatValueForTooltips(country, metric, target);
+ });
+ }
+
+ }
+
+ // if the view hasn't changed (but probably the selected metric),
+ // all we need to do is to recolor the current map.
+ if (target == self.lastSelected) {
+ updateColorsAndTooltips(metric);
+ return;
+ }
+
+ // otherwise we need to load another map svg
+ _updateMap(target + '.svg', function () {
+
+ // add a layer for non-selectable countries = for which no data is
+ // defined in the current report
+ map.addLayer('countries', {
+ name: 'context',
+ filter: function (pd) {
+ return UserCountryMap.countriesByIso[pd.iso] === undefined;
+ },
+ tooltips: function (pd) {
+ var countryName = pd.name;
+ for (var iso in self.config.countryNames) {
+ if (UserCountryMap.ISO2toISO3[iso.toUpperCase()] == pd.iso) {
+ countryName = self.config.countryNames[iso];
+ break;
+ }
+ }
+ return '
' + countryName + ' ' + _.no_visit;
+ }
+ });
+
+ // add a layer for selectable countries = for which we have data
+ // available in the current report
+ map.addLayer('countries', { name: 'countryBG', filter: function (pd) {
+ return UserCountryMap.countriesByIso[pd.iso] !== undefined;
+ }});
+
+ map.addLayer('countries', {
+ key: 'iso',
+ filter: function (pd) {
+ return UserCountryMap.countriesByIso[pd.iso] !== undefined;
+ },
+ click: function (data, path, evt) {
+ evt.stopPropagation();
+ // Remove row evolution. We don't want to expose data to general users.
+ var tgt;
+ if (self.lastSelected != 'world' || UserCountryMap.countriesByIso[data.iso] === undefined) {
+ tgt = data.iso;
+ } else {
+ tgt = UserCountryMap.ISO3toCONT[data.iso];
+ }
+ hasUserZoomed = true;
+ updateState(tgt);
+ }
+ });
+
+ updateColorsAndTooltips(metric);
+ });
+ }
+
+ /*
+ * updateMap is called by renderCountryMap() and renderWorldMap()
+ */
+ function _updateMap(svgUrl, callback) {
+ map.loadMap(config.svgBasePath + svgUrl, function () {
+
+ map.clear();
+ self.resize();
+ callback();
+
+ $('.ui-tooltip').remove(); // remove all existing tooltips
+
+ }, { padding: -3});
+ }
+
+ function indicateLoading() {
+ $$('.UserCountryMap-black').show();
+ $$('.UserCountryMap-black').css('opacity', 0);
+ $$('.UserCountryMap-black').animate({ opacity: 0.5 }, 400);
+ $$('.UserCountryMap .loadingPiwik').show();
+ }
+
+ function loadingComplete() {
+ $$('.UserCountryMap-black').hide();
+ $$('.UserCountryMap .loadingPiwik').hide();
+ }
+
+ /*
+ * returns a quantifiable value for a given metric
+ */
+ function quantify(d, metric) {
+ if (!metric) metric = $$('.userCountryMapSelectMetrics').val();
+ switch (metric) {
+ default:
+ return d[metric];
+ }
+ }
+
+ /*
+ * Aggregates a list of report rows by a given grouping function
+ *
+ * the groupBy function gets a row as argument add should return a
+ * group-id or false, if the row should be ignored.
+ *
+ * all rows for which groupBy returns the same group-id are
+ * aggregated according to the given metric.
+ */
+ function aggregate(rows, groupBy) {
+
+ var groups = {};
+ $.each(rows, function (i, row) {
+ var g_id = groupBy ? groupBy(row) : 'X';
+ g_id = g_id === true ? $.isNumeric(i) && i === Number(i) ? false : i : g_id;
+ if (g_id) {
+ if (!groups[g_id]) {
+ groups[g_id] = {
+ nb_visits: 0,
+ nb_actions: 0,
+ sum_visit_length: 0,
+ bounce_count: 0
+ };
+ }
+ $.each(groups[g_id], function (metric) {
+ groups[g_id][metric] += row[metric];
+ });
+ }
+ });
+
+ $.each(groups, function (g_id, group) {
+ var apv = group.nb_actions / group.nb_visits,
+ ats = group.sum_visit_length / group.nb_visits,
+ br = group.bounce_count / group.nb_visits;
+ group['nb_actions_per_visit'] = apv;
+ group['avg_time_on_site'] = new Date(0, 0, 0, ats / 3600, ats % 3600 / 60, ats % 60).toLocaleTimeString();
+ group['bounce_rate'] = (br % 1 !== 0 ? br.toFixed(1) : br) + "%";
+ });
+
+ return groupBy ? groups : groups.X;
+ }
+
+ function displayUnlocatableCount(unlocated, total, regionOrCity) {
+ $('.unlocated-stats').html(
+ $('.unlocated-stats').data('tpl')
+ .replace('%s', unlocated)
+ .replace('%p', '(' + formatPercentage(unlocated / total) + ')')
+ .replace('%c', UserCountryMap.countriesByIso[self.lastSelected].name)
+ );
+ $('.UserCountryMap-info-btn').show();
+
+ var zoomTitle = '';
+ if (regionOrCity == 'region') {
+ zoomTitle = ' ' + _pk_translate('UserCountryMap_WithUnknownRegion', [unlocated]);
+ } else if (regionOrCity == 'city') {
+ zoomTitle = ' ' + _pk_translate('UserCountryMap_WithUnknownCity', [unlocated]);
+ }
+
+ if (unlocated && zoomTitle) {
+ if ($('.map-stats .unlocatableCount').length) {
+ $('.map-stats .unlocatableCount').html(zoomTitle);
+ } else {
+ $('.map-stats').append('
' + zoomTitle + ' ');
+ }
+ }
+ }
+
+ /*
+ * renders a country map (either region or city view)
+ */
+ function renderCountryMap(iso) {
+
+ var countryMap = {
+ zoomed: false,
+ lastRequest: false,
+ lastResponse: false
+ };
+
+ /*
+ * updates the colors in the current region map
+ * this happens once a new country is loaded and
+ * whenever the metric changes
+ */
+ function updateRegionColors() {
+ indicateLoading();
+ // load data from Piwik API
+ ajax(_reportParams('UserCountry', 'getRegion', UserCountryMap.countriesByIso[iso].iso2))
+ .done(function (data) {
+ convertBounceRatesToPercents(data);
+
+ loadingComplete();
+
+ var regionDict = {},
+ totalCountryVisits = UserCountryMap.countriesByIso[iso].nb_visits,
+ unlocated = totalCountryVisits;
+ // self.lastReportMetricStats = {};
+
+ function regionCode(region) {
+ var key = UserCountryMap.keys[iso] || 'fips';
+ return key.substr(0, 4) == "fips" ? (region[key] || "").substr(2) : region[key]; // cut first two letters from fips code (=country code)
+ }
+
+ function regionExistsInMap(code) {
+ var key = UserCountryMap.keys[iso] || 'fips', q = {};
+ q[key] = key.substr(0, 4) == 'fips' ? UserCountryMap.countriesByIso[iso].fips + code : code;
+ if (map.getLayer('regions').getPaths(q).length === 0) {
+ return false;
+ }
+ return true;
+ }
+
+ $.each(data.reportData, function (i, row) {
+ regionDict[data.reportMetadata[i].region] = $.extend(row, data.reportMetadata[i], {
+ curMetric: quantify(row, metric)
+ });
+ });
+
+ var metric = $$('.userCountryMapSelectMetrics').val();
+
+ if (UserCountryMap.aggregate[iso]) {
+ var aggregated = aggregate(regionDict, function (row) {
+ var id = row.region, res = false;
+ $.each(UserCountryMap.aggregate[iso].groups, function (group, codes) {
+ if ($.inArray(id, codes) > -1) {
+ res = group;
+ }
+ });
+ return res;
+ });
+ //if (!UserCountryMap.aggregate.partial) regionDict = {};
+ $.each(aggregated, function (id, group) {
+ group.curMetric = quantify(group, metric);
+ regionDict[id] = group;
+ });
+ }
+
+ $.each(regionDict, function (key, region) {
+ if (regionExistsInMap(key)) unlocated -= region.nb_visits;
+ });
+ displayUnlocatableCount(unlocated, totalCountryVisits, 'region');
+
+ // create color scale
+ colscale = getColorScale(regionDict, 'curMetric', null, true);
+
+ function regionFill(data) {
+ var code = regionCode(data);
+ return regionDict[code] === undefined ? unknownRegionFillColor : colscale(regionDict[code].curMetric);
+ }
+
+ // apply colors to map
+ map.getLayer('regions')
+ .style('fill', regionFill)
+ .style('stroke',function (data) {
+ return regionDict[regionCode(data)] === undefined ? unknownRegionStrokeColor : regionStrokeColor;
+ }).sort(function (data) {
+ var code = regionCode(data);
+ return regionDict[code] === undefined ? -1 : regionDict[code].curMetric;
+ }).tooltips(function (data) {
+ var metric = $$('.userCountryMapSelectMetrics').val(),
+ region = regionDict[regionCode(data)];
+ if (region === undefined) {
+ return '
' + data.name + ' ' + _.nb_visits.replace('%s', '0 ') + '
';
+ }
+ return '
' + data.name + ' ' +
+ formatValueForTooltips(region, metric, iso);
+ }).on('click',function (d, path, evt) {
+ var region = regionDict[regionCode(d)];
+ if (region && region.label) {
+ map.getLayer('regions').style('fill', regionFill);
+ }
+ }).on('mouseenter',function (d, path, evt) {
+ var region = regionDict[regionCode(d)];
+ if (region && region.label) {
+ if (evt.shiftKey) {
+ path.attr('fill', regionHighlightColor);
+ }
+ }
+ }).on('mouseleave',function (d, path, evt) {
+ var region = regionDict[regionCode(d)];
+ if (region && region.label) {
+ if ($.inArray(region.label, _rowEvolution.labels) == -1) {
+ // reset color
+ path.attr('fill', regionFill(d));
+ }
+ }
+ }).style('cursor', function (d) {
+ return regionDict[regionCode(d)] && regionDict[regionCode(d)].label ? 'pointer' : 'default';
+ });
+
+ // check for regions missing in the map
+ $.each(regionDict, function (code, region) {
+ if (!regionExistsInMap(code)) {
+ console.warn('possible region mismatch!', code, region.nb_visits);
+ }
+ });
+ });
+ }
+
+ /*
+ * updates the city symbols in the current map
+ * this happens once a new country is loaded and
+ * whenever the metric changes
+ */
+ function updateCitySymbols() {
+ // color regions in white as background for symbols
+ var layerName = self.mode != "region" ? "regions2" : "regions";
+ if (map.getLayer(layerName)) map.getLayer(layerName).style('fill', invisibleRegionBackgroundColor);
+
+ indicateLoading();
+
+ // get visits per city from API
+ ajax(_reportParams('UserCountry', 'getCity', UserCountryMap.countriesByIso[iso].iso2))
+ .done(function (data) {
+ convertBounceRatesToPercents(data);
+
+ loadingComplete();
+
+ var metric = $$('.userCountryMapSelectMetrics').val(),
+ colscale,
+ totalCountryVisits = UserCountryMap.countriesByIso[iso].nb_visits,
+ unlocated = totalCountryVisits,
+ cities = [];
+
+ // merge reportData and reportMetadata to cities array
+ $.each(data.reportData, function (i, row) {
+ unlocated -= row.nb_visits;
+ cities.push($.extend(row, data.reportMetadata[i], {
+ curMetric: quantify(row, metric)
+ }));
+ });
+
+ displayUnlocatableCount(unlocated, totalCountryVisits, 'city');
+
+ // sort by current metric
+ cities.sort(function (a, b) { return b.curMetric - a.curMetric; });
+
+ colscale = getColorScale(cities, metric);
+
+ // construct scale
+ var radscale = $K.scale.linear(cities.concat({ curMetric: 0 }), 'curMetric');
+
+ var area = map.container.width() * map.container.height(),
+ sumArea = 0,
+ f = {
+ nb_visits: 0.002,
+ nb_uniq_visitors: 0.002,
+ nb_actions: 0.002,
+ avg_time_on_site: 0.02,
+ nb_actions_per_visit: 0.02,
+ bounce_rate: 0.02
+ },
+ maxRad;
+
+ $.each(cities, function (i, city) {
+ sumArea += isNaN(city.curMetric) ? 0 : Math.pow(radscale(city.curMetric), 2);
+ });
+
+ maxRad = Math.sqrt(area * f[metric] / sumArea);
+
+ radscale = $K.scale.sqrt(cities.concat({ curMetric: 0 }), 'curMetric').range([2, maxRad + 2]);
+
+ var citySymbols = map.addSymbols({
+ type: $K.LabeledBubble,
+ data: cities,
+ clustering: 'noverlap',
+ clusteringOpts: {
+ size: 128,
+ tolerance: 0
+ },
+ title: function (d) {
+ var v = d.curMetric;
+ if (isNaN(v)) {
+ return '';
+ }
+
+ if (metric === 'bounce_rate') {
+ v = Number((''+ v).replace('%', ''));
+ } else if (metric === 'avg_time_on_site') {
+ v = Number(v);
+ }
+
+ if (isNaN(v)) {
+ return '';
+ }
+
+ if (radscale(v) > 10) {
+ return formatNumber(d.curMetric, metric);
+ }
+
+ return '';
+ },
+ labelattrs: {
+ fill: cityLabelColor,
+ 'font-size': 11,
+ stroke: false,
+ cursor: 'pointer'
+ },
+ filter: function (d) {
+ if (isNaN(d.lat) || isNaN(d.long)) return false;
+ return !!d.curMetric && d.curMetric !== '0';
+ },
+ aggregate: function (rows) {
+ var row = aggregate(rows);
+ row.city_names = [];
+ row.label = rows[0].label; // keep label of biggest city for row evolution
+ $.each(rows, function (i, r) {
+ row.city_names = row.city_names.concat(r.city_names ? r.city_names : [r.city_name]);
+ });
+ row.city_name = row.city_names[0] + (row.city_names.length > 1 ? ' ' + _.and_n_others.replace('%s', (row.city_names.length - 1)) : '');
+ row.curMetric = quantify(row, metric);
+ return row;
+ },
+ sortBy: 'radius desc',
+ location: function (city) { return [city.long, city.lat]; },
+ radius: function (city) {
+ var scale = radscale(city.curMetric);
+ if (isNaN(scale)) {
+ return 0.01;
+ }
+ return scale;
+ },
+ tooltip: function (city) {
+ return '
' + city.city_name + ' ' +
+ formatValueForTooltips(city, metric, iso);
+ },
+ attrs: function (city) {
+ var color = colscale(city.curMetric);
+ if (color && color.hex) {
+ color = color.hex();
+ }
+ return {
+ fill: color,
+ 'fill-opacity': 0.7,
+ stroke: cityStrokeColor,
+ cursor: 'pointer'
+ };
+ },
+ mouseenter: function (city, symbol, evt) {
+ symbol.path.attr({
+ 'fill-opacity': 1,
+ 'stroke': cityHighlightStrokeColor,
+ 'stroke-opacity': 1,
+ 'stroke-width': 2
+ });
+ if (evt.shiftKey) {
+ symbol.path.attr({ fill: cityHighlightFillColor });
+ if (symbol.label) symbol.label.attr({ fill: cityHighlightLabelColor });
+ }
+ },
+ mouseleave: function (city, symbol) {
+ symbol.path.attr({
+ 'fill-opacity': 0.7,
+ 'stroke-opacity': 1,
+ 'stroke-width': 1,
+ 'stroke': cityLabelColor
+ });
+ if ($.inArray(city.label, _rowEvolution.labels) == -1) {
+ symbol.path.attr({ fill: colscale(city.curMetric) });
+ if (symbol.label) symbol.label.attr({ fill: cityLabelFillColor });
+ }
+ },
+ click: function (city, symbol, evt) {
+ showRowEvolution('getCity', city.label);
+ citySymbols.update({
+ attrs: function (city) {
+ return { fill: colscale(city.curMetric) };
+ }
+ });
+ }
+ });
+ });
+ }
+
+ _updateMap(iso + '.svg', function () {
+
+ // add background
+ map.addLayer('context', {
+ key: 'iso',
+ filter: function (pd) {
+ return UserCountryMap.countriesByIso[pd.iso] === undefined;
+ }
+ });
+ map.addLayer('context', {
+ key: 'iso',
+ name: 'context-clickable',
+ filter: function (pd) {
+ return UserCountryMap.countriesByIso[pd.iso] !== undefined;
+ },
+ click: function (path, p, evt) { // add click events for surrounding countries
+ evt.stopPropagation();
+ hasUserZoomed = true;
+ updateState(path.iso);
+ },
+ tooltips: function (data) {
+ if (UserCountryMap.countriesByIso[data.iso] === undefined) {
+ return 'no data';
+ }
+ var metric = $$('.userCountryMapSelectMetrics').val(),
+ country = UserCountryMap.countriesByIso[data.iso];
+ return '
' + country.name + ' ' +
+ formatValueForTooltips(country, metric, 'world');
+ }
+ });
+ function isThisCountry(d) { return d.iso == iso;}
+
+ map.addLayer("context", {
+ name: "regionBG",
+ filter: isThisCountry
+ });
+ map.addLayer("context", {
+ name: "regionBG-fill",
+ filter: isThisCountry
+ });
+ map.addLayer('regions', {
+ key: 'fips',
+ name: self.mode != "region" ? "regions2" : "regions",
+ styles: {
+ stroke: regionLayerStrokeColor
+ },
+ click: function (d, p, evt) {
+ evt.stopPropagation();
+ }
+ });
+ function filtCountryLabels(data) {
+ return data.iso != iso &&
+ map.getLayer('context-clickable') &&
+ map.getLayer('context-clickable').getPath(data.iso) &&
+ Math.abs(map.getLayer('context-clickable').getPath(data.iso).path.area()) > 700;
+ }
+
+ // returns either the reference to the country polygon or a custom label
+ // position if defined in UserCountryMap.customLabelPositions
+ function countryLabelPos(data) {
+ var CLP = UserCountryMap.customLabelPositions;
+ if (CLP[iso] && CLP[iso][data.iso]) return CLP[iso][data.iso];
+ return 'context-clickable.' + data.iso;
+ }
+
+ map.addSymbols({
+ data: map.getLayer('context-clickable').getPathsData(),
+ type: $K.Label,
+ filter: filtCountryLabels,
+ location: countryLabelPos,
+ text: function (data) { return UserCountryMap.countriesByIso[data.iso].iso2; },
+ 'class': 'countryLabelBg'
+ });
+ map.addSymbols({
+ data: map.getLayer('context-clickable').getPathsData(),
+ type: $K.Label,
+ filter: filtCountryLabels,
+ location: countryLabelPos,
+ text: function (data) { return UserCountryMap.countriesByIso[data.iso].iso2; },
+ 'class': 'countryLabel'
+ });
+
+ if (!UserCountryMap.countriesByIso[iso]) return;
+
+ if (self.mode == "region") {
+ updateRegionColors();
+ } else {
+ updateCitySymbols();
+ }
+
+ });
+ }
+
+ var _rowEvolution = { labels: [], method: false };
+
+ // now load the metrics for all countries
+ ajax(_reportParams('UserCountry', 'getCountry'))
+ .done(function (report) {
+ convertBounceRatesToPercents(report);
+
+ var metrics = $$('.userCountryMapSelectMetrics option');
+ var countryData = [], countrySelect = $$('.userCountryMapSelectCountry'),
+ countriesByIso = {};
+ UserCountryMap.lastReportMetricStats = {};
+ // read api result to countryData and countriesByIso
+ $.each(report.reportData, function (i, data) {
+ var meta = report.reportMetadata[i],
+ country = {
+ name: data.label,
+ iso2: meta.code.toUpperCase(),
+ fips: meta.code.toUpperCase(),
+ iso: UserCountryMap.ISO2toISO3[meta.code.toUpperCase()],
+ flag: meta.logo
+ };
+ if (UserCountryMap.differentFIPS[country.iso2]) {
+ country.fips = UserCountryMap.differentFIPS[country.iso2];
+ }
+ $.each(metrics, function (i, metric) {
+ metric = $(metric).val();
+ country[metric] = data[metric];
+ });
+ countryData.push(country);
+ countriesByIso[country.iso] = country;
+ worldTotalVisits += country['nb_visits'];
+ });
+ _worldTotal = worldTotalVisits;
+ // sort countries by name
+ countryData.sort(function (a, b) { return a.name > b.name ? 1 : -1; });
+
+ // store country data globally
+ UserCountryMap.countryData = countryData;
+ UserCountryMap.countriesByIso = countriesByIso;
+
+ function postCSSLoad() {
+ // map stylesheets are loaded
+
+ // hide loading indicator
+ $$('.UserCountryMap .loadingPiwik').hide();
+ $('.mapWidgetStatus').height(0);
+
+ // start with default view (or saved state??)
+ var params = self.widget.dashboardWidget('getWidgetObject').parameters;
+ self.mode = params && params.viewMode ? params.viewMode : 'region';
+ if (params && params.lastMetric) $$('.userCountryMapSelectMetrics').val(params.lastMetric);
+ // alert('updateState: '+params && params.lastMap ? params.lastMap : 'world');
+
+ // populate country select
+ var isoCodes = [];
+ $.each(countryData, function (i, country) {
+ if (!!country.iso) {
+ isoCodes.push(country.iso);
+ countrySelect.append('
' + country.name + ' ');
+ }
+ });
+
+ if (!hasUserZoomed && isoCodes.length === 1 && isoCodes[0] && isoCodes[0] !== 'UNK') {
+ updateState(isoCodes[0]);
+ } else {
+ updateState(params && params.lastMap ? params.lastMap : 'world');
+ }
+
+ initUserInterface();
+
+ }
+ // check if CSS is already loaded
+ if (!$("link[href='" + config.mapCssPath + "']").length) {
+ // not loaded
+ map.loadCSS(config.mapCssPath, postCSSLoad);
+ } else {
+ // already loaded
+ postCSSLoad();
+ }
+ });
+
+ function hideOverlay(e) {
+ var overlay = $('.content', $(e.target).parents('.UserCountryMap-overlay'));
+ if (overlay.data('locked')) return;
+ overlay.data('locked', true);
+ overlay.fadeOut(200);
+
+ $$('.UserCountryMap').mouseleave(function () {
+ overlay.fadeIn(200);
+ $$('.UserCountryMap').parent().off('mouseleave');
+ setTimeout(function () {
+ overlay.data('locked', false);
+ }, 1000);
+ });
+ var offset = $$('.UserCountryMap').offset(),
+ dim = {
+ x: overlay.offset().left - offset.left,
+ y: overlay.offset().top - offset.top,
+ w: overlay.width(),
+ h: overlay.height()
+ };
+ $$('.UserCountryMap').mousemove(function (e) {
+ var mx = e.pageX - offset.left, my = e.pageY - offset.top, pad = 20,
+ outside = mx < dim.x - pad || mx > dim.x + dim.w + pad || my < dim.y - pad || my > dim.y + dim.h + pad;
+ if (outside) {
+ $$('.UserCountryMap').parent().off('mouseleave');
+ setTimeout(function () {
+ overlay.fadeIn(200);
+ setTimeout(function () {
+ overlay.data('locked', false);
+ }, 1000);
+ }, 100);
+ }
+ });
+ /*setTimeout(function() {
+ overlay.fadeIn(1000);
+ }, 3000);*/
+ }
+
+ $('.UserCountryMap-overlay').off('mouseenter').on('mouseenter', hideOverlay);
+ $$('.widgetUserCountryMapIslandoravisitorMap .widgetName span').remove();
+ $$('.widgetUserCountryMapIslandoravisitorMap .widgetName').append('
');
+
+ // converts bounce rate quotients to numeric percents, eg, .12 => 12
+ function convertBounceRatesToPercents(report) {
+ $.each(report.reportData, function (i, row) {
+ if (row['bounce_rate']) {
+ row['bounce_rate'] = parseFloat(row['bounce_rate']) * 100;
+ }
+ });
+ }
+ },
+
+ /*
+ * resizes the map
+ */
+ resize: function () {
+ var ratio, w, h,
+ map = this.map;
+
+ ratio = map.viewAB.width / map.viewAB.height;
+ w = map.container.width();
+ h = w / ratio;
+
+ // special handling for widgetize mode
+ if (!this.theWidget && map.container.parents('.widget').length) {
+ var maxHeight = $(window).height() - ($('html').height() - map.container.height());
+ h = Math.min(maxHeight, h);
+ }
+
+ map.container.height(h - 2);
+ map.resize(w, h);
+
+ if (w < 355) $('.UserCountryMapIslandora .tableIcon span').hide();
+ else $('.UserCountryMapIslandora .tableIcon span').show();
+ },
+
+ /*
+ * removes the map
+ */
+ destroy: function () {
+ this.map.clear();
+ $(this.map.container).html('');
+ $(window).off('resize', this._onResizeLazy)
+ }
+
+ });
+
+}());
+
+/*
+ * Some static data used both by VisitorMap and RealtimeMap
+ */
+$.extend(UserCountryMap, {
+
+ // iso alpha-2 --> iso alpha-3
+ ISO2toISO3: {"BD": "BGD", "BE": "BEL", "BF": "BFA", "BG": "BGR", "BA": "BIH", "BB": "BRB", "WF": "WLF", "BL": "BLM", "BM": "BMU", "BN": "BRN", "BO": "BOL", "BH": "BHR", "BI": "BDI", "BJ": "BEN", "BT": "BTN", "JM": "JAM", "BV": "BVT", "BW": "BWA", "WS": "WSM", "BQ": "BES", "BR": "BRA", "BS": "BHS", "JE": "JEY", "BY": "BLR", "BZ": "BLZ", "RU": "RUS", "RW": "RWA", "RS": "SRB", "TL": "TLS", "RE": "REU", "TM": "TKM", "TJ": "TJK", "RO": "ROU", "TK": "TKL", "GW": "GNB", "GU": "GUM", "GT": "GTM", "GS": "SGS", "GR": "GRC", "GQ": "GNQ", "GP": "GLP", "JP": "JPN", "GY": "GUY", "GG": "GGY", "GF": "GUF", "GE": "GEO", "GD": "GRD", "GB": "GBR", "GA": "GAB", "SV": "SLV", "GN": "GIN", "GM": "GMB", "GL": "GRL", "GI": "GIB", "GH": "GHA", "OM": "OMN", "TN": "TUN", "JO": "JOR", "HR": "HRV", "HT": "HTI", "HU": "HUN", "HK": "HKG", "HN": "HND", "HM": "HMD", "VE": "VEN", "PR": "PRI", "PS": "PSE", "PW": "PLW", "PT": "PRT", "SJ": "SJM", "PY": "PRY", "IQ": "IRQ", "PA": "PAN", "PF": "PYF", "PG": "PNG", "PE": "PER", "PK": "PAK", "PH": "PHL", "PN": "PCN", "PL": "POL", "PM": "SPM", "ZM": "ZMB", "EH": "ESH", "EE": "EST", "EG": "EGY", "ZA": "ZAF", "EC": "ECU", "IT": "ITA", "VN": "VNM", "SB": "SLB", "ET": "ETH", "SO": "SOM", "ZW": "ZWE", "SA": "SAU", "ES": "ESP", "ER": "ERI", "ME": "MNE", "MD": "MDA", "MG": "MDG", "MF": "MAF", "MA": "MAR", "MC": "MCO", "UZ": "UZB", "MM": "MMR", "ML": "MLI", "MO": "MAC", "MN": "MNG", "MH": "MHL", "MK": "MKD", "MU": "MUS", "MT": "MLT", "MW": "MWI", "MV": "MDV", "MQ": "MTQ", "MP": "MNP", "MS": "MSR", "MR": "MRT", "IM": "IMN", "UG": "UGA", "TZ": "TZA", "MY": "MYS", "MX": "MEX", "IL": "ISR", "FR": "FRA", "IO": "IOT", "SH": "SHN", "FI": "FIN", "FJ": "FJI", "FK": "FLK", "FM": "FSM", "FO": "FRO", "NI": "NIC", "NL": "NLD", "NO": "NOR", "NA": "NAM", "VU": "VUT", "NC": "NCL", "NE": "NER", "NF": "NFK", "NG": "NGA", "NZ": "NZL", "NP": "NPL", "NR": "NRU", "NU": "NIU", "CK": "COK", "XK": "XKX", "CI": "CIV", "CH": "CHE", "CO": "COL", "CN": "CHN", "CM": "CMR", "CL": "CHL", "CC": "CCK", "CA": "CAN", "CG": "COG", "CF": "CAF", "CD": "COD", "CZ": "CZE", "CY": "CYP", "CX": "CXR", "CS": "SCG", "CR": "CRI", "CW": "CUW", "CV": "CPV", "CU": "CUB", "SZ": "SWZ", "SY": "SYR", "SX": "SXM", "KG": "KGZ", "KE": "KEN", "SS": "SSD", "SR": "SUR", "KI": "KIR", "KH": "KHM", "KN": "KNA", "KM": "COM", "ST": "STP", "SK": "SVK", "KR": "KOR", "SI": "SVN", "KP": "PRK", "KW": "KWT", "SN": "SEN", "SM": "SMR", "SL": "SLE", "SC": "SYC", "KZ": "KAZ", "KY": "CYM", "SG": "SGP", "SE": "SWE", "SD": "SDN", "DO": "DOM", "DM": "DMA", "DJ": "DJI", "DK": "DNK", "VG": "VGB", "DE": "DEU", "YE": "YEM", "DZ": "DZA", "US": "USA", "UY": "URY", "YT": "MYT", "UM": "UMI", "LB": "LBN", "LC": "LCA", "LA": "LAO", "TV": "TUV", "TW": "TWN", "TT": "TTO", "TR": "TUR", "LK": "LKA", "LI": "LIE", "LV": "LVA", "TO": "TON", "LT": "LTU", "LU": "LUX", "LR": "LBR", "LS": "LSO", "TH": "THA", "TF": "ATF", "TG": "TGO", "TD": "TCD", "TC": "TCA", "LY": "LBY", "VA": "VAT", "VC": "VCT", "AE": "ARE", "AD": "AND", "AG": "ATG", "AF": "AFG", "AI": "AIA", "VI": "VIR", "IS": "ISL", "IR": "IRN", "AM": "ARM", "AL": "ALB", "AO": "AGO", "AN": "ANT", "AQ": "ATA", "AS": "ASM", "AR": "ARG", "AU": "AUS", "AT": "AUT", "AW": "ABW", "IN": "IND", "AX": "ALA", "AZ": "AZE", "IE": "IRL", "ID": "IDN", "UA": "UKR", "QA": "QAT", "MZ": "MOZ"},
+
+ // iso alpha-3 --> continent code
+ ISO3toCONT: {"AGO": "AF", "DZA": "AF", "EGY": "AF", "BGD": "AS", "NER": "AF", "LIE": "EU", "NAM": "AF", "BGR": "EU", "BOL": "SA", "GHA": "AF", "CCK": "AS", "PAK": "AS", "CPV": "AF", "JOR": "AS", "LBR": "AF", "LBY": "AF", "MYS": "AS", "DOM": "NA", "PRI": "NA", "SXM": "NA", "PRK": "AS", "PSE": "AS", "TZA": "AF", "BWA": "AF", "KHM": "AS", "UMI": "OC", "NIC": "NA", "TTO": "NA", "ETH": "AF", "PRY": "SA", "HKG": "AS", "SAU": "AS", "LBN": "AS", "SVN": "EU", "BFA": "AF", "CHE": "EU", "MRT": "AF", "HRV": "EU", "CHL": "SA", "CHN": "AS", "KNA": "NA", "SLE": "AF", "JAM": "NA", "SMR": "EU", "GIB": "EU", "DJI": "AF", "GIN": "AF", "FIN": "EU", "URY": "SA", "THA": "AS", "STP": "AF", "SYC": "AF", "NPL": "AS", "CXR": "AS", "LAO": "AS", "YEM": "AS", "BVT": "AN", "ZAF": "AF", "KIR": "OC", "PHL": "AS", "ROU": "EU", "VIR": "NA", "SYR": "AS", "MAC": "AS", "MAF": "NA", "MLT": "EU", "KAZ": "AS", "TCA": "NA", "PYF": "OC", "NIU": "OC", "DMA": "NA", "BEN": "AF", "GUF": "SA", "BEL": "EU", "MSR": "NA", "TGO": "AF", "DEU": "EU", "GUM": "OC", "LKA": "AS", "SSD": "AF", "FLK": "SA", "GBR": "EU", "BES": "NA", "GUY": "SA", "CRI": "NA", "CMR": "AF", "MAR": "AF", "MNP": "OC", "LSO": "AF", "HUN": "EU", "TKM": "AS", "SUR": "SA", "NLD": "EU", "BMU": "NA", "HMD": "AN", "TCD": "AF", "GEO": "AS", "MNE": "EU", "MNG": "AS", "MHL": "OC", "MTQ": "NA", "BLZ": "NA", "NFK": "OC", "MMR": "AS", "AFG": "AS", "BDI": "AF", "VGB": "NA", "BLR": "EU", "BLM": "NA", "GRD": "NA", "TKL": "OC", "GRC": "EU", "RUS": "EU", "GRL": "NA", "SHN": "AF", "AND": "EU", "MOZ": "AF", "TJK": "AS", "XKX": "EU", "HTI": "NA", "MEX": "NA", "ANT": "NA", "ZWE": "AF", "LCA": "NA", "IND": "AS", "LVA": "EU", "BTN": "AS", "VCT": "NA", "VNM": "AS", "NOR": "EU", "CZE": "EU", "ATF": "AN", "ATG": "NA", "FJI": "OC", "IOT": "AS", "HND": "NA", "MUS": "AF", "ATA": "AN", "LUX": "EU", "ISR": "AS", "FSM": "OC", "PER": "SA", "REU": "AF", "IDN": "AS", "VUT": "OC", "MKD": "EU", "COD": "AF", "COG": "AF", "ISL": "EU", "GLP": "NA", "COK": "OC", "COM": "AF", "COL": "SA", "NGA": "AF", "TLS": "OC", "TWN": "AS", "PRT": "EU", "MDA": "EU", "GGY": "EU", "MDG": "AF", "ECU": "SA", "SEN": "AF", "NZL": "OC", "MDV": "AS", "ASM": "OC", "SPM": "NA", "CUW": "NA", "FRA": "EU", "LTU": "EU", "RWA": "AF", "ZMB": "AF", "GMB": "AF", "WLF": "OC", "JEY": "EU", "FRO": "EU", "GTM": "NA", "DNK": "EU", "IMN": "EU", "AUS": "OC", "AUT": "EU", "SJM": "EU", "VEN": "SA", "PLW": "OC", "KEN": "AF", "MYT": "AF", "WSM": "OC", "TUR": "AS", "ALB": "EU", "OMN": "AS", "TUV": "OC", "ALA": "EU", "BRN": "AS", "TUN": "AF", "PCN": "OC", "BRB": "NA", "BRA": "SA", "CIV": "AF", "SRB": "EU", "GNQ": "AF", "USA": "NA", "QAT": "AS", "SWE": "EU", "AZE": "AS", "GNB": "AF", "SWZ": "AF", "TON": "OC", "CAN": "NA", "UKR": "EU", "KOR": "AS", "AIA": "NA", "CAF": "AF", "SVK": "EU", "CYP": "EU", "BIH": "EU", "SGP": "AS", "SGS": "AN", "SOM": "AF", "UZB": "AS", "ERI": "AF", "POL": "EU", "KWT": "AS", "SCG": "EU", "GAB": "AF", "CYM": "NA", "VAT": "EU", "EST": "EU", "MWI": "AF", "ESP": "EU", "IRQ": "AS", "SLV": "NA", "MLI": "AF", "IRL": "EU", "IRN": "AS", "ABW": "NA", "PNG": "OC", "PAN": "NA", "SDN": "AF", "SLB": "OC", "ESH": "AF", "MCO": "EU", "ITA": "EU", "JPN": "AS", "KGZ": "AS", "UGA": "AF", "NCL": "OC", "ARE": "AS", "ARG": "SA", "BHS": "NA", "BHR": "AS", "ARM": "AS", "NRU": "OC", "CUB": "NA"},
+
+ // special region aggregation for some countries
+ aggregate: {
+ GBR: {
+ groups: {
+ "East Midlands": ["H5", "D2", "D3", "H7", "J1", "H4", "L4", "J8", "J9"],
+ "West Midlands": ["", "O2", "P3", "F7", "Q4", "N1", "N4", "L6"],
+ "South West": ["E6", "A4", "B7", "J4", "M6", "M3", "D4", "B2", "D6", "K5", "C6", "K4", "O4", "N9", "P8"],
+ "North East": ["", "D1", "D8", "F5", "I5", "K9", "N3", "J6"],
+ "Scotland": ["U4", "U5", "U7", "V2", "V4", "U5", "V8", "W2", "W4", "W5", "W7", "T5", "T6", "U9", "V9", "W6", "U1", "W1", "T7", "U3", "V1", "U6", "U8", "V5", "W9", "T9", "U2", "U9", "V3", "T8", "W8"],
+ "South East": ["F2", "M4", "I6", "B9", "", "B6", "E2", "I3", "P6", "K2", "N7", "G2", "K6", "G5"],
+ "North West": ["", "E9", "C5", "A8", "H2", "C9", "P2", "I2"],
+ "Yorkshire and the Humber": ["G6", "J2", "J3", "Q5", "E1", "J7", "", ""],
+ "Northern Ireland": ["R3", "S6", "T3", "Q8", "S9", "R2", "R8", "S1", "S5", "R7", "Q6", "S7", "Q9", "S3", "R4", "T1", "T2", "R9", "R6", "R1", "S4", "R5", "T4", "S2", "Q7", "S8"],
+ "London": ["H9", "A1", "A6", "B5", "B8", "C4", "C8", "D9", "E3", "E7", "F1", "G1", "G3", "G4", "I4", "K8", "L1", "N8", "O5", "O9", "P1", "P5", "F6", "F9", "G7", "E8", "F3", "F4", "H1", "H6", "I8", "M8"],
+ "East": ["M5", "A5", "F8", "C3", "E4", "N5", "I9", "O3", "I1", "K3"],
+ "Wales": ["X7", "X6", "Y7", "Y8", "X3", "X4", "Y3", "Y9", "X5", "Z3", "Y5", "Z1", "X9", "Y1", "Z4", "X1", "X8", "Y2", "X2", "Y4", "Y6", "Z2"]
+ }
+ },
+ SVN: {
+ groups: {
+ "PS": ["08", "54", "B6"],
+ "NO": ["I7", "00", "13", "38", "91", "94"],
+ "KO": ["E6", "93", "A4", "00", "A5", "16", "25", "74", "76", "81", "A2", "C2"],
+ "SP": ["14", "36", "D2", "01", "06", "07", "44", "46", "J5", "E1", "84", "00"],
+ "LJ": ["D4", "E3", "E5", "G4", "G7", "H6", "00", "00", "00", "00", "05", "09", "22", "32", "37", "39", "I5", "61", "64", "68", "71", "72", "77", "C1"],
+ "JP": ["19", "35", "40", "49", "50", "J9", "B7"],
+ "JS": ["00", "J7", "L1", "00", "00", "00", "00", "00", "00", "17", "66", "73", "B1", "B4", "B8", "D4"],
+ "PD": ["42", "28", "42", "87", "E9", "00", "00", "00", "18", "I3", "J1", "K7", "L3", "L8", "N2", "00", "00", "00", "00", "00", "00", "00", "00", "00", "70", "00", "00", "26", "45", "55", "89", "98", "B3", "C8"],
+ "GO": ["03", "04", "32", "52", "53", "62", "A3", "B9", "D5", "F1", "F2", "K5", "00", "H4", "00", "12", "B2"],
+ "SA": ["D7", "E2", "F3", "I9", "92", "L7", "N3", "N5", "00", "00", "00", "00", "00", "00", "00", "00", "00", "", "11", "30", "08", "57", "62", "79", "83", "99", "A7", "A8", "C4", "C5", "C6", "C7", "C9"],
+ "ZS": ["E7", "34", "C9", "C9"],
+ "PM": ["02", "47", "78", "80", "86", "D1", "D6", "33", "I2", "00", "00", "15", "59", "I6", "00", "00", "00", "00", "00", "10", "29", "97", "97", "A1", "A6"]
+ }
+ },
+ FRA: {
+ partial: true,
+ groups: {
+ "A5": ["A5", "B5"]
+ }
+ },
+ POL: {
+ partial: true,
+ groups: {
+ "82": ["82", "60"],
+ "85": ["85", "47", "H9"]
+ }
+ },
+ CZE: {
+ partial: true,
+ groups: {
+ "82": ["82", "70", "23", "20"],
+ "88": ["88", "41"]
+ }
+ },
+ BEL: {
+ partial: true,
+ groups: {
+ "12": ["12", "02"]
+ }
+ },
+ DNK: {
+ partial: true,
+ groups: {
+ "19": ["19", "07"],
+ "18": ["18", "15"],
+ "20": ["20", "12"],
+ "21": ["21", "11", "04"]
+ }
+ }
+ },
+
+ // which key should be used, defaults to fips
+ keys: {
+ "SVN": "region",
+ "GBR": "region",
+ "ESP": "fips-",
+ "USA": "p", "CAN": "p"
+ },
+
+ // custom country label positions [lon, lat]
+ customLabelPositions: {
+ CZE: { DEU: [12.3, 49] },
+ DEU: { AUT: [13.9, 48.1] },
+ ESP: { PRT: [-8.5, 39.6] },
+ NLD: { BEL: [4.6, 51, 1], DEU: [6.9, 51.5] },
+ CHE: { FRA: [6.2, 47.2], AUT: [9.95, 47.2], ITA: [9.7, 46.0], DEU: [8.14, 47.83] },
+ USA: { MEX: [-102, 24], CAN: [-97, 52] },
+ BIH: { HRV: [15.3, 45] }
+ },
+
+ // countries where FIPS differs from 2-letter ISO code
+ differentFIPS: {
+ AD: 'AN', AG: 'AC', AI: 'AV', AQ: 'AY', AS: 'AQ', AT: 'AU', AU: 'AS', AW: 'AA',
+ AZ: 'AJ', BA: 'BK', BD: 'BG', BF: 'UV', BG: 'BU', BH: 'BA', BI: 'BY', BJ: 'BN',
+ BL: 'TB', BM: 'BD', BN: 'BX', BO: 'BL', BS: 'BF', BW: 'BC', BY: 'BO', BZ: 'BH',
+ CC: 'CK', CD: 'CG', CF: 'CT', CG: 'CF', CH: 'SZ', CI: 'IV', CK: 'CW', CL: 'CI',
+ CN: 'CH', CR: 'CS', CW: 'UC', CX: 'KT', CZ: 'EZ', DE: 'GM', DK: 'DA', DM: 'DO',
+ DO: 'DR', DZ: 'AG', EE: 'EN', EH: 'WI', ES: 'SP', GA: 'GB', GB: 'UK', GD: 'GJ',
+ GE: 'GG', GF: 'FG', GG: 'GK', GM: 'GA', GN: 'GV', GQ: 'EK', GS: 'SX', GU: 'GQ',
+ GW: 'PU', HN: 'HO', HT: 'HA', IE: 'EI', IL: 'IS', IQ: 'IZ', IS: 'IC', JP: 'JA',
+ KH: 'CB', KI: 'KR', KM: 'CN', KN: 'SC', KP: 'KN', KR: 'KS', XK: 'KV', KW: 'KU',
+ KY: 'CJ', LB: 'LE', LC: 'ST', LI: 'LS', LK: 'CE', LR: 'LI', LS: 'LT', LT: 'LH',
+ LV: 'LG', MA: 'MO', MC: 'MN', ME: 'MJ', MF: 'RN', MG: 'MA', MH: 'RM', MM: 'BM',
+ MN: 'MG', MO: 'MC', MP: 'CQ', MQ: 'MB', MS: 'MH', MU: 'MP', MW: 'MI', NA: 'WA',
+ NE: 'NG', NG: 'NI', NI: 'NU', NU: 'NE', OM: 'MU', PA: 'PM', PF: 'FP', PG: 'PP',
+ PH: 'RP', PM: 'SB', PN: 'PC', PR: 'RQ', PS: 'WE', PT: 'PO', PW: 'PS', PY: 'PA',
+ RS: 'RI', RU: 'RS', SB: 'BP', SC: 'SE', SD: 'SU', SS: 'OD', SE: 'SW', SG: 'SN',
+ SJ: 'SV', SK: 'LO', SN: 'SG', SR: 'NS', ST: 'TP', SV: 'ES', SX: 'NN', SZ: 'WZ',
+ TC: 'TK', TD: 'CD', TF: 'FS', TG: 'TO', TJ: 'TI', TK: 'TL', TL: 'TT', TM: 'TX',
+ TN: 'TS', TO: 'TN', TR: 'TU', TT: 'TD', UA: 'UP', VA: 'VT', VG: 'VI', VI: 'VQ',
+ VN: 'VM', VU: 'NH', YE: 'YM', YT: 'MF', ZA: 'SF', ZM: 'ZA', ZW: 'ZI', CS: 'YI',
+ AN: 'NT'
+ },
+
+ // mapping from Piwik continents to continents used in this widget
+ cont2cont: {
+ afr: 'AF', eur: 'EU', amn: 'NA', ams: 'SA', asi: 'AS', oce: 'OC', amc: 'SA'
+ }
+
+});
+
diff --git a/lang/ar.json b/lang/ar.json
new file mode 100644
index 0000000..b9b4de2
--- /dev/null
+++ b/lang/ar.json
@@ -0,0 +1,5 @@
+{
+ "UserCountryMapIslandora": {
+ "map": "خريطة"
+ }
+}
\ No newline at end of file
diff --git a/lang/be.json b/lang/be.json
new file mode 100644
index 0000000..fcadccd
--- /dev/null
+++ b/lang/be.json
@@ -0,0 +1,5 @@
+{
+ "UserCountryMapIslandora": {
+ "map": "карта"
+ }
+}
\ No newline at end of file
diff --git a/lang/bg.json b/lang/bg.json
new file mode 100644
index 0000000..c0500cc
--- /dev/null
+++ b/lang/bg.json
@@ -0,0 +1,22 @@
+{
+ "UserCountryMapIslandora": {
+ "AndNOthers": "и %s други",
+ "Cities": "Градове",
+ "Countries": "Държави",
+ "DaysAgo": "преди %s дни",
+ "GoalConversions": "%s достигнати цели",
+ "HoursAgo": "преди %s часа",
+ "map": "карта",
+ "MinutesAgo": "преди %s минути",
+ "None": "Няма",
+ "NoVisit": "Няма посещения",
+ "RealTimeMap": "Карта на посетителите в реално време",
+ "Regions": "Региони",
+ "Searches": "%s търсения",
+ "SecondsAgo": "преди %s секунди",
+ "ShowingVisits": "Последни посещения базирани на географско местоположение",
+ "Unlocated": "
%s<\/b> %p посещения от %c вашето местоположение не може да бъде открито.",
+ "VisitorMap": "Карта на посетителите",
+ "WorldWide": "По целия свят"
+ }
+}
\ No newline at end of file
diff --git a/lang/bn.json b/lang/bn.json
new file mode 100644
index 0000000..730e84e
--- /dev/null
+++ b/lang/bn.json
@@ -0,0 +1,5 @@
+{
+ "UserCountryMapIslandora": {
+ "None": "কিছুই না"
+ }
+}
\ No newline at end of file
diff --git a/lang/ca.json b/lang/ca.json
new file mode 100644
index 0000000..e58c532
--- /dev/null
+++ b/lang/ca.json
@@ -0,0 +1,6 @@
+{
+ "UserCountryMapIslandora": {
+ "map": "mapa",
+ "ShowingVisits": "Visites geolocalitzades des de l'última vegada"
+ }
+}
\ No newline at end of file
diff --git a/lang/cs.json b/lang/cs.json
new file mode 100644
index 0000000..97e9264
--- /dev/null
+++ b/lang/cs.json
@@ -0,0 +1,25 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Tento modul poskytuje widgety Mapa návštěvníků a Real-time Mapa. Poznámka: Vyžaduje povolený UserCountry plugin.",
+ "AndNOthers": "a %s dalších",
+ "Cities": "Města",
+ "Countries": "Země",
+ "DaysAgo": "před %s dny",
+ "GoalConversions": "%s konverzí cíle",
+ "HoursAgo": "před %s hodinami",
+ "map": "mapa",
+ "MinutesAgo": "před %s minutami",
+ "None": "Žádní",
+ "NoVisit": "Žádná návštěva",
+ "RealTimeMap": "Mapa v reálném čase",
+ "Regions": "Regiony",
+ "Searches": "%s vyhledávání",
+ "SecondsAgo": "před %s sekundami",
+ "ShowingVisits": "Geolokované návštěvy posledních",
+ "Unlocated": "%s<\/b> %p z návštěv z %c nebylo možné geolokovat.",
+ "VisitorMap": "Mapa návštěvníků",
+ "WorldWide": "Celosvětová",
+ "WithUnknownRegion": "%s s neznámým regionem",
+ "WithUnknownCity": "%s s neznámým městem"
+ }
+}
\ No newline at end of file
diff --git a/lang/da.json b/lang/da.json
new file mode 100644
index 0000000..7e017dd
--- /dev/null
+++ b/lang/da.json
@@ -0,0 +1,25 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Denne udvidelse leverer de to widgets Besøgerkort og Realtidskort. Bemærk: Kræver at BrugerLand-udvidelsen er aktiveret.",
+ "AndNOthers": "og %s andre",
+ "Cities": "Byer",
+ "Countries": "Lande",
+ "DaysAgo": "%s dage siden",
+ "GoalConversions": "%s målkonverteringer",
+ "HoursAgo": "%s timer siden",
+ "map": "kort",
+ "MinutesAgo": "%s minutter siden",
+ "None": "Ingen",
+ "NoVisit": "Ingen besøg",
+ "RealTimeMap": "Realtidskort",
+ "Regions": "Regioner",
+ "Searches": "%s søgninger",
+ "SecondsAgo": "%s sekunder siden",
+ "ShowingVisits": "Geografisk placeret besøg af sidste",
+ "Unlocated": "%s<\/b> besøg %p fra %c kunne ikke placeres geografisk.",
+ "VisitorMap": "Besøgerkort",
+ "WorldWide": "Hele verden",
+ "WithUnknownRegion": "%s med ukendt region",
+ "WithUnknownCity": "%s med ukendt by"
+ }
+}
\ No newline at end of file
diff --git a/lang/de.json b/lang/de.json
new file mode 100644
index 0000000..2aed99a
--- /dev/null
+++ b/lang/de.json
@@ -0,0 +1,27 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Dieses Plugin stellt die Widgets \"Besucherkarte\" sowie \"Besucherkarte in Echtzeit\" bereit. Hinweis: Hierfür muss das Plugin \"UserCountry\" aktiviert sein.",
+ "AndNOthers": "und %s andere",
+ "Cities": "Städte",
+ "Countries": "Länder",
+ "DaysAgo": "vor %s Tagen",
+ "GoalConversions": "%s Ziel-Konversionen",
+ "HoursAgo": "vor %s Stunden",
+ "map": "Karte",
+ "MinutesAgo": "vor %s Minuten",
+ "None": "Keine",
+ "NoVisit": "Keine Besuche",
+ "RealTimeMap": "Besucherkarte in Echtzeit",
+ "Regions": "Regionen",
+ "Searches": "%s Suchen",
+ "SecondsAgo": "vor %s Sekunden",
+ "ShowingVisits": "Lokalisierte Besuche der letzten",
+ "Unlocated": "%s<\/b> %p der Besuche von %c konnten nicht lokalisiert werden.",
+ "VisitorMap": "Besucherkarte",
+ "WorldWide": "Weltweit",
+ "WithUnknownRegion": "%s mit unbekannter Region",
+ "WithUnknownCity": "%s mit unbekannter Stadt",
+ "NoVisitsInfo": "Es werden aktuell keine Besuche angezeigt, weil für diesen Zeitraum kein Besuch mit korrekten Geolocation Informationen (Längengrad & Breitengrad) existiert.",
+ "NoVisitsInfo2": "Um das Problem zu lösen, stellen Sie sicher, dass Sie einen GeoIP Geolocation Provider mit einer GeoIP Stadt Datenbank verwenden. Wenn dies Ihr Problem nicht löst, dann ist es möglich (wenn auch unwahrscheinlich) dass Ihre Besuche IP Adressen haben, die nicht geolokalisiert werden können."
+ }
+}
\ No newline at end of file
diff --git a/lang/el.json b/lang/el.json
new file mode 100644
index 0000000..3f4d6fe
--- /dev/null
+++ b/lang/el.json
@@ -0,0 +1,27 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Το πρόσθετο αυτό παρέχει το γραφικό συστατικό Χάρτης Επισκεπτών και τον Χάρτη Σε Πραγματικό Χρόνο. Σημείωση: Απαιτεί να είναι ενεργοποιημένο το πρόσθετο UserCountry.",
+ "AndNOthers": "και %s άλλοι",
+ "Cities": "Πόλεις",
+ "Countries": "Χώρες",
+ "DaysAgo": "πριν %s ημέρες",
+ "GoalConversions": "%s μετατροπές στόχων",
+ "HoursAgo": "πριν %s ώρες",
+ "map": "χάρτης",
+ "MinutesAgo": "πριν %s λεπτά",
+ "None": "Κανένα",
+ "NoVisit": "Δεν υπάρχουν επισκέψεις",
+ "RealTimeMap": "Χάρτης σε πραγματικό χρόνο",
+ "Regions": "Περιοχές",
+ "Searches": "%s αναζητήσεις",
+ "SecondsAgo": "πριν %s δευτερόλεπτα",
+ "ShowingVisits": "Επισκέψεις με γεωτοποθεσία στα τελευταία",
+ "Unlocated": "%s<\/b> %p από τις επισκέψεις από %c δεν ήταν δυνατόν να χαρακτηριστούν με γεωτοποθεσία.",
+ "VisitorMap": "Χάρτης Επισκεπτών",
+ "WorldWide": "Παγκοσμίως",
+ "WithUnknownRegion": "%s με άγνωστη περιοχή",
+ "WithUnknownCity": "%s με άγνωστη πόλη",
+ "NoVisitsInfo": "Δεν εμφανίζονται αυτή τη στιγμή επισκέψεις, διότι δεν υπήρξε επίσκεψη για αυτήν την περίοδο με σωστή πληροφορία γεωτοποθεσίας (πλάτος και μήκος).",
+ "NoVisitsInfo2": "Για να λυθεί το ζήτημα, βεβαιωθείτε ότι χρησιμοποιείτε ένα πάροχο γεωτοποθεσίας με βάση δεδομένων πόλεων. Αν αυτό δεν λύσει το θέμα σας, τότε υπάρχει περίπτωση (όμως όχι τόσο πιθανό) ότι έχετε επισκέψεις με διευθύνσεις IP που δεν επιλύονται στην γεωτοποθεσία τους."
+ }
+}
\ No newline at end of file
diff --git a/lang/en.json b/lang/en.json
new file mode 100644
index 0000000..8a57b1e
--- /dev/null
+++ b/lang/en.json
@@ -0,0 +1,27 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "This plugin provides the widgets Visitor Map and Real-time Map. Note: Requires the UserCountry plugin enabled.",
+ "AndNOthers": "and %s others",
+ "Cities": "Cities",
+ "Countries": "Countries",
+ "DaysAgo": "%s days ago",
+ "GoalConversions": "%s goal conversions",
+ "HoursAgo": "%s hours ago",
+ "map": "map",
+ "MinutesAgo": "%s minutes ago",
+ "None": "None",
+ "NoVisit": "No visit",
+ "RealTimeMap": "Real-time Map",
+ "Regions": "Regions",
+ "Searches": "%s searches",
+ "SecondsAgo": "%s seconds ago",
+ "ShowingVisits": "Geo-located visits of last",
+ "Unlocated": "%s<\/b> %p of the visits from %c couldn't be geo located.",
+ "VisitorMap": "Visitor Map",
+ "WorldWide": "World-Wide",
+ "WithUnknownRegion": "%s with unknown region",
+ "WithUnknownCity": "%s with unknown city",
+ "NoVisitsInfo": "There are no visits displayed currently, because no visit for this period has the correct geolocation information (latitude & longitude).",
+ "NoVisitsInfo2": "To resolve this issue, make sure you are using a GeoIP geolocation provider with a GeoIP city database. If this does not resolve your issue, then it is possible (though unlikely) that your visits have IP addresses that just cannot be geolocated."
+ }
+}
\ No newline at end of file
diff --git a/lang/es-ar.json b/lang/es-ar.json
new file mode 100644
index 0000000..ed32736
--- /dev/null
+++ b/lang/es-ar.json
@@ -0,0 +1,22 @@
+{
+ "UserCountryMapIslandora": {
+ "AndNOthers": "y %s otros",
+ "Cities": "Ciudades",
+ "Countries": "Países",
+ "DaysAgo": "Hace %s días",
+ "GoalConversions": "%s conversiones de objetivo",
+ "HoursAgo": "Hace %s horas",
+ "map": "mapa",
+ "MinutesAgo": "Hace %s minutos",
+ "None": "Ninguno",
+ "NoVisit": "Ninguna visita",
+ "RealTimeMap": "Mapa en Tiempo Real",
+ "Regions": "Regiones",
+ "Searches": "%s búsquedas",
+ "SecondsAgo": "Hace %s segundos",
+ "ShowingVisits": "Geo-ubicadas últimas visitas",
+ "Unlocated": "%s<\/b> %p de las visitas desde %c no pudieron ser geo ubicadas.",
+ "VisitorMap": "Mapa de Visitantes",
+ "WorldWide": "Mundial"
+ }
+}
\ No newline at end of file
diff --git a/lang/es.json b/lang/es.json
new file mode 100644
index 0000000..02a989a
--- /dev/null
+++ b/lang/es.json
@@ -0,0 +1,27 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Este complemento suministra los módulos Mapa de visitante y Mapa en tiempo real. Nota: Requiere el complemento UserCountry habilitado.",
+ "AndNOthers": "y %s otros",
+ "Cities": "Ciudades",
+ "Countries": "Países",
+ "DaysAgo": "%s días atrás",
+ "GoalConversions": "%s conversiones de objetivo",
+ "HoursAgo": "%s horas atrás",
+ "map": "mapa",
+ "MinutesAgo": "Hace %s minutos",
+ "None": "Ninguno",
+ "NoVisit": "Sin visitas",
+ "RealTimeMap": "Mapa en Tiempo real",
+ "Regions": "Regiones",
+ "Searches": "%s búsquedas",
+ "SecondsAgo": "Hace %s segundos",
+ "ShowingVisits": "Visitas geolocalizadas desde la última vez",
+ "Unlocated": "%s<\/b> %p de las visitas desde %c no pudieron ser geolocalizadas.",
+ "VisitorMap": "Mapa de visitantes",
+ "WorldWide": "Global",
+ "WithUnknownRegion": "%s con región desconocida",
+ "WithUnknownCity": "%s con ciudad desconocida",
+ "NoVisitsInfo": "No hay visitas mostradas actualmente, porque ninguna visita para este período tiene la información de geolocalización correcta (latitud y longitud).",
+ "NoVisitsInfo2": "Para resolver este problema, asegúrese de que está utilizando un proveedor de geolocalización GeoIP con una base de datos de la ciudad GeoIP. Si esto no resuelve su problema, entonces es posible (aunque improbable) que sus visitas tengan direcciones IP que simplemente no se puedan geolocalizar."
+ }
+}
\ No newline at end of file
diff --git a/lang/et.json b/lang/et.json
new file mode 100644
index 0000000..44f0bf0
--- /dev/null
+++ b/lang/et.json
@@ -0,0 +1,21 @@
+{
+ "UserCountryMapIslandora": {
+ "AndNOthers": "ja %s muud",
+ "Cities": "Linnad",
+ "Countries": "Riigid",
+ "DaysAgo": "%s päeva tagasi",
+ "GoalConversions": "%s tulutoovaid eesmärke",
+ "HoursAgo": "%s tundi tagasi",
+ "map": "kaart",
+ "MinutesAgo": "%s minutit tagasi",
+ "None": "Mitte ükski",
+ "NoVisit": "Külastused puuduvad",
+ "RealTimeMap": "Reaalaja kaart",
+ "Regions": "Regioonid",
+ "Searches": "%s otsingut",
+ "SecondsAgo": "%s sekundit tagasi",
+ "ShowingVisits": "Tuvastatud asukohaga külastused viimase",
+ "VisitorMap": "Külastuste kaart",
+ "WorldWide": "Globaalne"
+ }
+}
\ No newline at end of file
diff --git a/lang/fa.json b/lang/fa.json
new file mode 100644
index 0000000..b76142e
--- /dev/null
+++ b/lang/fa.json
@@ -0,0 +1,21 @@
+{
+ "UserCountryMapIslandora": {
+ "AndNOthers": "و%s سایر",
+ "Cities": "شهرها",
+ "Countries": "کشورها",
+ "DaysAgo": "%s روز پیش",
+ "GoalConversions": "%s تبدیل هدف",
+ "HoursAgo": "%s ساعت پیش",
+ "map": "نقشه",
+ "MinutesAgo": "%s دقیقه پیش",
+ "None": "هیچ",
+ "NoVisit": "بدون بازدید",
+ "RealTimeMap": "نقشه در همین لحظه",
+ "Regions": "منطقه ها",
+ "Searches": "%sجستجو",
+ "SecondsAgo": "%s ثانیه پیش",
+ "ShowingVisits": "مکان اخرین بازدید کنندگان",
+ "VisitorMap": "نقشه بازدیدکننده",
+ "WorldWide": "سراسر جهان"
+ }
+}
\ No newline at end of file
diff --git a/lang/fi.json b/lang/fi.json
new file mode 100644
index 0000000..9bda533
--- /dev/null
+++ b/lang/fi.json
@@ -0,0 +1,25 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Tämä lisäosa tarjoaa käyttäjäkartan ja reaaliaikakartan. Huom: \"UserCountry\"-liitännäisen tulee olla päällä.",
+ "AndNOthers": "ja %s muuta",
+ "Cities": "Kaupungit",
+ "Countries": "Maat",
+ "DaysAgo": "%s päivää sitten",
+ "GoalConversions": "%s tavoitekonversiot",
+ "HoursAgo": "%s tuntia sitten",
+ "map": "kartta",
+ "MinutesAgo": "%s minuuttia sitten",
+ "None": "Ei mitään",
+ "NoVisit": "Ei käyntejä",
+ "RealTimeMap": "Reaaliaikainen kartta",
+ "Regions": "Alueet",
+ "Searches": "%s hakua",
+ "SecondsAgo": "%s sekuntia sitten",
+ "ShowingVisits": "Geopaikannetut käynnit viimeiset",
+ "Unlocated": "%s<\/b> %p käynneistä %c:sta ei voitu geopaikantaa.",
+ "VisitorMap": "Kartta kävijöistä",
+ "WorldWide": "Maailmanlaajuinen",
+ "WithUnknownRegion": "%s tuntemattomalta alueelta",
+ "WithUnknownCity": "%s tuntemattomista kaupungeista"
+ }
+}
\ No newline at end of file
diff --git a/lang/fr.json b/lang/fr.json
new file mode 100644
index 0000000..289bfd8
--- /dev/null
+++ b/lang/fr.json
@@ -0,0 +1,27 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Ce composant fournit les gadgets Carte du Visiteur et Carte en temps réel. Note : requiert que le composant Pays du Visiteur soit activé.",
+ "AndNOthers": "et %s autres",
+ "Cities": "Villes",
+ "Countries": "Pays",
+ "DaysAgo": "%s jours",
+ "GoalConversions": "%s conversions d'objectifs",
+ "HoursAgo": "%s heures",
+ "map": "carte",
+ "MinutesAgo": "%s minutes",
+ "None": "aucun",
+ "NoVisit": "Aucune visite",
+ "RealTimeMap": "Carte en temps-réel",
+ "Regions": "Régions",
+ "Searches": "%s recherches",
+ "SecondsAgo": "%s secondes",
+ "ShowingVisits": "Dernières visites géo-localisées",
+ "Unlocated": "%s<\/b> %p des dernières visites de %c n'ont pas pu être géo-localisées.",
+ "VisitorMap": "Carte des visiteurs",
+ "WorldWide": "Mondialement",
+ "WithUnknownRegion": "%s avec une région inconnue",
+ "WithUnknownCity": "%s avec une ville inconnue",
+ "NoVisitsInfo": "Il n'y a aucune visite affichée en ce moment car aucune visite pour cette période n'a les bonnes informations de géolocalisation (latitude & longitude).",
+ "NoVisitsInfo2": "Afin de résoudre ce problème, assurez-vous que vous utilisez un fournisseur de géolocalisation GeoIP avec une base de donnée GeoIP City. Si cela ne résout pas votre problème, il est possible (mais improbable) que vos visites ont des adresses IP qui ne peuvent pas être géolocalisées."
+ }
+}
\ No newline at end of file
diff --git a/lang/he.json b/lang/he.json
new file mode 100644
index 0000000..2dc9981
--- /dev/null
+++ b/lang/he.json
@@ -0,0 +1,10 @@
+{
+ "UserCountryMapIslandora": {
+ "Cities": "ערים",
+ "Countries": "מדינות",
+ "map": "מפה",
+ "MinutesAgo": "לפני %s דקות",
+ "VisitorMap": "מפת מבקרים",
+ "WorldWide": "כלל-עולמי"
+ }
+}
\ No newline at end of file
diff --git a/lang/hi.json b/lang/hi.json
new file mode 100644
index 0000000..85ae98b
--- /dev/null
+++ b/lang/hi.json
@@ -0,0 +1,23 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "इस प्लगइन विगेट्स आगंतुक मानचित्र और वास्तविक समय का नक्शा प्रदान करता है। नोट: सक्षम UserCountry प्लगइन की आवश्यकता है।",
+ "AndNOthers": "और %s दूसरों के",
+ "Cities": "शहरों",
+ "Countries": "देश",
+ "DaysAgo": "%s दिन पहले",
+ "GoalConversions": "%s लक्ष्य रूपांतरण",
+ "HoursAgo": "%s घंटे पहले",
+ "map": "नक्शा",
+ "MinutesAgo": "%s मिनट पहले",
+ "None": "कोई नहीं",
+ "NoVisit": "कोई यात्रा",
+ "RealTimeMap": "वास्तविक समय नक्शा",
+ "Regions": "क्षेत्र",
+ "Searches": "%s खोजों",
+ "SecondsAgo": "%s सेकंड पहले",
+ "ShowingVisits": "आखिरी का भू स्थित दौरा",
+ "Unlocated": "%s<\/b> %p से यात्राओं की %c भौगोलिक स्थित खोजा नहीं जा सकता है.",
+ "VisitorMap": "आगंतुक मानचित्र",
+ "WorldWide": "विश्व व्यापक"
+ }
+}
\ No newline at end of file
diff --git a/lang/hr.json b/lang/hr.json
new file mode 100644
index 0000000..552db23
--- /dev/null
+++ b/lang/hr.json
@@ -0,0 +1,5 @@
+{
+ "UserCountryMapIslandora": {
+ "VisitorMap": "Mapa posjetitelja"
+ }
+}
\ No newline at end of file
diff --git a/lang/hu.json b/lang/hu.json
new file mode 100644
index 0000000..923d186
--- /dev/null
+++ b/lang/hu.json
@@ -0,0 +1,5 @@
+{
+ "UserCountryMapIslandora": {
+ "map": "térkép"
+ }
+}
\ No newline at end of file
diff --git a/lang/id.json b/lang/id.json
new file mode 100644
index 0000000..5df2af1
--- /dev/null
+++ b/lang/id.json
@@ -0,0 +1,25 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Pengaya ini menyediakan gawit Peta Pengunjung dan Peta Waktu-Nyata. Catatan: Membutuhkan pengaya NegaraPengguna diaktifkan.",
+ "AndNOthers": "dan %s lain",
+ "Cities": "Kita",
+ "Countries": "Negara",
+ "DaysAgo": "%s hari lalu",
+ "GoalConversions": "%s konversi tujuan",
+ "HoursAgo": "%s jam lalu",
+ "map": "peta",
+ "MinutesAgo": "%s menit lalu",
+ "None": "Tidak Ada",
+ "NoVisit": "Tidak ada kunjungan",
+ "RealTimeMap": "Peta Waktu-Nyata",
+ "Regions": "Wilayah",
+ "Searches": "%s pencarian",
+ "SecondsAgo": "%s detik lalu",
+ "ShowingVisits": "Kunjungan Lokasi-Geo terakhir",
+ "Unlocated": "%s<\/b> %p kunjungan dari %c lokasi-geo tidak diketahui.",
+ "VisitorMap": "Peta Pengunjung",
+ "WorldWide": "Seluruh Dunia",
+ "WithUnknownRegion": "%s dengan wilayah tidak dikenal",
+ "WithUnknownCity": "%s dengan kota tidak dikenal"
+ }
+}
\ No newline at end of file
diff --git a/lang/it.json b/lang/it.json
new file mode 100644
index 0000000..65ece6b
--- /dev/null
+++ b/lang/it.json
@@ -0,0 +1,27 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Questo plugin fornisce i widget Mappa Visitatori e Mappa in Tempo Reale. Richiede che sia abilitato il plugin UserCountry.",
+ "AndNOthers": "e %s altri",
+ "Cities": "Città",
+ "Countries": "Nazioni",
+ "DaysAgo": "%s giorni fa",
+ "GoalConversions": "%s conversioni obiettivi",
+ "HoursAgo": "%s ore fa",
+ "map": "mappa",
+ "MinutesAgo": "%s minuti fa",
+ "None": "Nessuno",
+ "NoVisit": "Nessuna visita",
+ "RealTimeMap": "Mappa Real Time",
+ "Regions": "Regioni",
+ "Searches": "%s ricerche",
+ "SecondsAgo": "%s secondi fa",
+ "ShowingVisits": "Visite geolocalizzate degli ultimi",
+ "Unlocated": "%s<\/b> %p delle visite da %c non possono essere geolocalizzate.",
+ "VisitorMap": "Mappa Visitatori",
+ "WorldWide": "Tutto il Mondo",
+ "WithUnknownRegion": "%s con regione sconosciuta",
+ "WithUnknownCity": "%s con città sconosciuta",
+ "NoVisitsInfo": "Al momento non vengono mostrate visite, poiché in questo periodo non ci sono visite con le corrette informazioni di geo-localizzazione (latitudine\/longitudine)",
+ "NoVisitsInfo2": "Per risolvere questo problema, assicurati di utilizzare un provider di geo-localizzazione GeoIP con un database di città GeoIP. Se ciò non risolve il tuo problema, è possibile (anche se improbabile) che le tue visite abbiano degli indirizzi IP che proprio non possono essere geo-localizzati."
+ }
+}
\ No newline at end of file
diff --git a/lang/ja.json b/lang/ja.json
new file mode 100644
index 0000000..576637d
--- /dev/null
+++ b/lang/ja.json
@@ -0,0 +1,27 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "このプラグインでは、ビジターマップとリアルタイムマップウィジェットを提供します。注:利用可能なユーザーカントリープラグインが必要。",
+ "AndNOthers": "と、%s ほか",
+ "Cities": "都市",
+ "Countries": "国",
+ "DaysAgo": "%s 日前",
+ "GoalConversions": "%s 目標コンバージョン",
+ "HoursAgo": "%s 時間前",
+ "map": "地図",
+ "MinutesAgo": "%s 分前",
+ "None": "なし",
+ "NoVisit": "訪問なし",
+ "RealTimeMap": "リアルタイムマップ",
+ "Regions": "地域",
+ "Searches": "%s 検索",
+ "SecondsAgo": "%s 秒前",
+ "ShowingVisits": "位置情報が探索された最後の訪問",
+ "Unlocated": "%c からの訪問の %s <\/b> %p は、位置情報が特定できませんでした。",
+ "VisitorMap": "ビジターマップ",
+ "WorldWide": "世界規模",
+ "WithUnknownRegion": "未知の地域と %s",
+ "WithUnknownCity": "未知の都市と %s",
+ "NoVisitsInfo": "この期間のビジットには、正しい地理情報(緯度と経度)がないため、現在表示されているビジットはありません。",
+ "NoVisitsInfo2": "この問題を解決するには、GeoIP ジオロケーションプロバイダを GeoIP の都市データベースで使用していることを確認してください。 これで問題が解決しない場合、このビジットには地理的に配置できない IP アドレスが含まれている可能性(通常ではありえませんが)があります。"
+ }
+}
\ No newline at end of file
diff --git a/lang/ka.json b/lang/ka.json
new file mode 100644
index 0000000..1d9a882
--- /dev/null
+++ b/lang/ka.json
@@ -0,0 +1,5 @@
+{
+ "UserCountryMapIslandora": {
+ "map": "რუკა"
+ }
+}
\ No newline at end of file
diff --git a/lang/ko.json b/lang/ko.json
new file mode 100644
index 0000000..d499013
--- /dev/null
+++ b/lang/ko.json
@@ -0,0 +1,25 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "이 플러그인은 방문자 지도 및 실시간 지도 위젯을 제공합니다. 주의: UserCountry 플러그인이 활성화 되어 있어야 합니다.",
+ "AndNOthers": ", 기타 %s",
+ "Cities": "도시",
+ "Countries": "국가",
+ "DaysAgo": "%s일 전",
+ "GoalConversions": "%s 목표 전환",
+ "HoursAgo": "%s시간 전",
+ "map": "지도",
+ "MinutesAgo": "%s분 전",
+ "None": "없음",
+ "NoVisit": "방문 없음",
+ "RealTimeMap": "실시간 지도",
+ "Regions": "지역",
+ "Searches": "%s 검색",
+ "SecondsAgo": "%s초 전",
+ "ShowingVisits": "최근 방문의 지리적 위치",
+ "Unlocated": "%s<\/b> %c 방문에서 %p의 지리적 위치를 찾을 수 없습니다.",
+ "VisitorMap": "방문자 지도",
+ "WorldWide": "전세계",
+ "WithUnknownRegion": "%s 알 수 없는 지역",
+ "WithUnknownCity": "%s 알 수 없는 도시"
+ }
+}
\ No newline at end of file
diff --git a/lang/lt.json b/lang/lt.json
new file mode 100644
index 0000000..d09b294
--- /dev/null
+++ b/lang/lt.json
@@ -0,0 +1,10 @@
+{
+ "UserCountryMapIslandora": {
+ "Countries": "Šalys",
+ "DaysAgo": "Prieš %s dienų",
+ "HoursAgo": "Prieš %s valandų",
+ "map": "žemėlapis",
+ "MinutesAgo": "Prieš %s minučių",
+ "SecondsAgo": "Prieš %s sekundžių"
+ }
+}
\ No newline at end of file
diff --git a/lang/lv.json b/lang/lv.json
new file mode 100644
index 0000000..7d3637d
--- /dev/null
+++ b/lang/lv.json
@@ -0,0 +1,5 @@
+{
+ "UserCountryMapIslandora": {
+ "map": "karte"
+ }
+}
\ No newline at end of file
diff --git a/lang/nb.json b/lang/nb.json
new file mode 100644
index 0000000..93f1763
--- /dev/null
+++ b/lang/nb.json
@@ -0,0 +1,25 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Denne utvidelsen gir deg widgetene Kart over besøkende og Sanntidskart. Merk: krever at UserCountry-utvidelsen er aktivert.",
+ "AndNOthers": "og %s andre",
+ "Cities": "Byer",
+ "Countries": "Land",
+ "DaysAgo": "%s dager siden",
+ "GoalConversions": "%s målkonverteringer",
+ "HoursAgo": "%s timer siden",
+ "map": "kart",
+ "MinutesAgo": "%s minutter siden",
+ "None": "Ingen",
+ "NoVisit": "Ingen besøk",
+ "RealTimeMap": "Sanntidskart",
+ "Regions": "Regioner",
+ "Searches": "%s søk",
+ "SecondsAgo": "%s sekunder siden",
+ "ShowingVisits": "Stedsbestemte besøk siste",
+ "Unlocated": "%s<\/b> %p av besøkene fra %c kunne ikke stedsbestemmes.",
+ "VisitorMap": "Kart over besøkende",
+ "WorldWide": "Verdensbasis",
+ "WithUnknownRegion": "%s med ukjent region",
+ "WithUnknownCity": "%s med ukjent by"
+ }
+}
\ No newline at end of file
diff --git a/lang/nl.json b/lang/nl.json
new file mode 100644
index 0000000..7214ef5
--- /dev/null
+++ b/lang/nl.json
@@ -0,0 +1,25 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Deze plugin verzorgt de widgets Bezoekers landkaart en Real-time landkaart. Opmerking: Vereist dat de UserCountry plugin is ingeschakeld.",
+ "AndNOthers": "en %s anderen",
+ "Cities": "Steden",
+ "Countries": "Landen",
+ "DaysAgo": "%s dagen geleden",
+ "GoalConversions": "%s doelconversies",
+ "HoursAgo": "%s uur geleden",
+ "map": "kaart",
+ "MinutesAgo": "%s minuten geleden",
+ "None": "Geen",
+ "NoVisit": "Geen bezoek",
+ "RealTimeMap": "Realtime Kaart",
+ "Regions": "Regio's",
+ "Searches": "%s zoekopdrachten",
+ "SecondsAgo": "%s seconden geleden",
+ "ShowingVisits": "Gelokaliseerde bezoeken van laatste",
+ "Unlocated": "%s<\/b> %p van de bezoeken vanaf %c konden niet worden gelokaliseerd.",
+ "VisitorMap": "Bezoekersmap",
+ "WorldWide": "Wereldwijd",
+ "WithUnknownRegion": "%s met onbekende regio",
+ "WithUnknownCity": "%s met onbekende stad"
+ }
+}
\ No newline at end of file
diff --git a/lang/pl.json b/lang/pl.json
new file mode 100644
index 0000000..bc22f1b
--- /dev/null
+++ b/lang/pl.json
@@ -0,0 +1,25 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Wtyczka dostarcza widżetów Mapa Odwiedzin i Mapa Czasu Rzeczywistego. NOTKA: Wymaga włączenia wtyczki UserCountry.",
+ "AndNOthers": "i %s innych",
+ "Cities": "Miasta",
+ "Countries": "Państw",
+ "DaysAgo": "%s dni temu",
+ "GoalConversions": "%s konwersji celów",
+ "HoursAgo": "%s godzin temu",
+ "map": "mapa",
+ "MinutesAgo": "%s minut temu",
+ "None": "Brak",
+ "NoVisit": "Brak wizyt",
+ "RealTimeMap": "Mapa Czasu Rzeczywistego",
+ "Regions": "Regiony",
+ "Searches": "%s wyszukań",
+ "SecondsAgo": "%s sekund temu",
+ "ShowingVisits": "Geolokalizowane wizyty z ostatnich",
+ "Unlocated": "%s<\/b> %p wizyt z %c nie mogło zostać zlokalizowane.",
+ "VisitorMap": "Mapa Odwiedzin",
+ "WorldWide": "World-Wide",
+ "WithUnknownRegion": "%s z nieznanego regionu",
+ "WithUnknownCity": "%s z nieznanego miasta"
+ }
+}
\ No newline at end of file
diff --git a/lang/pt-br.json b/lang/pt-br.json
new file mode 100644
index 0000000..280d019
--- /dev/null
+++ b/lang/pt-br.json
@@ -0,0 +1,27 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Este plugin fornece os widgets Mapa de Visitantes e o Mapa Tempo-Real. Nota: Requer o plugin UserCountry ativado.",
+ "AndNOthers": "e %s outros",
+ "Cities": "Cidades",
+ "Countries": "Países",
+ "DaysAgo": "%s dias atrás",
+ "GoalConversions": "%s conversões de meta",
+ "HoursAgo": "%s horas atrás",
+ "map": "mapa",
+ "MinutesAgo": "%s minutos atrás",
+ "None": "Nenhum",
+ "NoVisit": "Nenhuma visita",
+ "RealTimeMap": "Mapa em tempo real",
+ "Regions": "Regiões",
+ "Searches": "%s buscas",
+ "SecondsAgo": "%s segundos atrás",
+ "ShowingVisits": "Geo-localização das últimas visitas",
+ "Unlocated": "%s<\/b> %p das visitas de %c não puderam ser geo localizados.",
+ "VisitorMap": "Mapa de visitantes",
+ "WorldWide": "World-Wide",
+ "WithUnknownRegion": "%s com região desconhecida",
+ "WithUnknownCity": "%s com cidade desconhecida",
+ "NoVisitsInfo": "Não há visitas exibidas atualmente, porque nenhuma visita para este período possui a informação de geolocalização correta (latitude e longitude).",
+ "NoVisitsInfo2": "Para resolver este problema, verifique se você está usando um provedor de geolocalização GeoIP com um banco de cidades GeoIP. Se isso não resolver o problema, é possível (embora improvável) que suas visitas tenham endereços IPs que não possam ser geolocalizados."
+ }
+}
\ No newline at end of file
diff --git a/lang/pt.json b/lang/pt.json
new file mode 100644
index 0000000..7854663
--- /dev/null
+++ b/lang/pt.json
@@ -0,0 +1,27 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Esta extensão fornece as widgets do Mapa de visitantes e o Mapa em tempo real. Nota: Requer que a extensão UserCountry esteja ativa.",
+ "AndNOthers": "e %s outros",
+ "Cities": "Cidades",
+ "Countries": "Países",
+ "DaysAgo": "Há %s dias",
+ "GoalConversions": "%s conversões de objetivos",
+ "HoursAgo": "Há %s horas",
+ "map": "mapa",
+ "MinutesAgo": "Há %s minutos",
+ "None": "Nenhum",
+ "NoVisit": "Nenhuma visita",
+ "RealTimeMap": "Mapa em tempo real",
+ "Regions": "Regiões",
+ "Searches": "%s pesquisas",
+ "SecondsAgo": "Há %s segundos",
+ "ShowingVisits": "Visitas geolocalizadas dos últimos",
+ "Unlocated": "%s<\/b> %p das visitas de %c não puderam ser geolocalizadas.",
+ "VisitorMap": "Mapa de visitantes",
+ "WorldWide": "Mundial",
+ "WithUnknownRegion": "%s com uma região desconhecida",
+ "WithUnknownCity": "%s com uma cidade desconhecida",
+ "NoVisitsInfo": "Não existem visitas atualmente a serem mostradas porque nenhuma visita para este período tem informações corretas de geolocalização (latitude e longitude).",
+ "NoVisitsInfo2": "Para resolver este problema, confirme que está a utilizar um fornecedor de localização GeoIP com uma base de dados GeoIP de cidades. Se isto não resolver o seu problema, então é possível (embora pouco provável) que as suas visitas têm endereços de IP que não podem ser geolocalizados."
+ }
+}
\ No newline at end of file
diff --git a/lang/ro.json b/lang/ro.json
new file mode 100644
index 0000000..22109ab
--- /dev/null
+++ b/lang/ro.json
@@ -0,0 +1,22 @@
+{
+ "UserCountryMapIslandora": {
+ "AndNOthers": "si %s altii",
+ "Cities": "Oraşe",
+ "Countries": "Ţări",
+ "DaysAgo": "%s zile în urmă",
+ "GoalConversions": "%s obiectivul conversiilor",
+ "HoursAgo": "%s ore în urmă",
+ "map": "harta",
+ "MinutesAgo": "%s acum cateva minute",
+ "None": "Nu sunt",
+ "NoVisit": "Nici o vizita",
+ "RealTimeMap": "Harta în timp real",
+ "Regions": "Regiuni",
+ "Searches": "%s cautari",
+ "SecondsAgo": "%s acum o secunda",
+ "ShowingVisits": "Ultimile vizite geo-localizate",
+ "Unlocated": "%s<\/b> %p vizitelor de la %c nu au putut fi geolocalizate.",
+ "VisitorMap": "Harta vizitatori",
+ "WorldWide": "World-Wide"
+ }
+}
\ No newline at end of file
diff --git a/lang/ru.json b/lang/ru.json
new file mode 100644
index 0000000..2117c8a
--- /dev/null
+++ b/lang/ru.json
@@ -0,0 +1,25 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Этот плагин предоставляет виджеты Visitor Map и Real-time Map. Внимание: требуется включенный плагин UserCountry.",
+ "AndNOthers": "и %s других",
+ "Cities": "Города",
+ "Countries": "Страны",
+ "DaysAgo": "%s дней назад",
+ "GoalConversions": "%s целей достигнуто",
+ "HoursAgo": "%s часов назад",
+ "map": "карта",
+ "MinutesAgo": "%s минут назад",
+ "None": "Нет",
+ "NoVisit": "Без посещений",
+ "RealTimeMap": "Карта в реальном времени",
+ "Regions": "Регионы",
+ "Searches": "%s поисковых запросов",
+ "SecondsAgo": "%s секунд назад",
+ "ShowingVisits": "Последние геолокационные посещения",
+ "Unlocated": "%s<\/b> %p посещения из %c не могут быть геолокализованны.",
+ "VisitorMap": "Карта посещений",
+ "WorldWide": "Весь мир",
+ "WithUnknownRegion": "%s с неизвестным регионом",
+ "WithUnknownCity": "%s с неизвестным городом"
+ }
+}
\ No newline at end of file
diff --git a/lang/sk.json b/lang/sk.json
new file mode 100644
index 0000000..48d6917
--- /dev/null
+++ b/lang/sk.json
@@ -0,0 +1,12 @@
+{
+ "UserCountryMapIslandora": {
+ "Cities": "Mestá",
+ "Countries": "Krajiny",
+ "map": "mapa",
+ "None": "Nič",
+ "NoVisit": "Žiadna návšteva",
+ "RealTimeMap": "Mapa v reálnom čase",
+ "Regions": "Regióny",
+ "VisitorMap": "Mapa návštev"
+ }
+}
\ No newline at end of file
diff --git a/lang/sl.json b/lang/sl.json
new file mode 100644
index 0000000..d2a08df
--- /dev/null
+++ b/lang/sl.json
@@ -0,0 +1,9 @@
+{
+ "UserCountryMapIslandora": {
+ "map": "zemljevid",
+ "RealTimeMap": "Zemljevid v realnem času",
+ "Regions": "Regije",
+ "VisitorMap": "Zemljevid obiskovalcev",
+ "WorldWide": "Cel svet"
+ }
+}
\ No newline at end of file
diff --git a/lang/sq.json b/lang/sq.json
new file mode 100644
index 0000000..6dd484e
--- /dev/null
+++ b/lang/sq.json
@@ -0,0 +1,27 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Kjo shtojcë ofron widget-et Hartë Vizitorësh dhe Hartë Në Kohë Reale. Shënim: Lyp shtojcën UserCountry të aktivizuar.",
+ "AndNOthers": "dhe %s të tjerë",
+ "Cities": "Qytete",
+ "Countries": "Vende",
+ "DaysAgo": "%s ditë më parë",
+ "GoalConversions": "%s shndërrime objektivash",
+ "HoursAgo": "%s orë më parë",
+ "map": "hartë",
+ "MinutesAgo": "%s minuta më parë",
+ "None": "Asnjë",
+ "NoVisit": "Pa vizita",
+ "RealTimeMap": "Hartë e Atypëratyshme",
+ "Regions": "Rajone",
+ "Searches": "%s kërkime",
+ "SecondsAgo": "%s sekonda më parë",
+ "ShowingVisits": "Vizita të gjeovendëzuara, për pjesën e fundit të",
+ "Unlocated": "%s<\/b> %p e vizitës prej %c s’u gjeovendëzua dot.",
+ "VisitorMap": "Hartë Vizitorësh",
+ "WorldWide": "Anembanë Botës",
+ "WithUnknownRegion": "%s me rajon të panjohur",
+ "WithUnknownCity": "%s me qytet të panjohur",
+ "NoVisitsInfo": "Hëpërhë s’ka vizita të shfaqura, ngaqë për këtë periudhë asnjë vizitë nuk ka të dhëna të sakta gjeolokalizimi (gjerësi & gjatësi gjeografike).",
+ "NoVisitsInfo2": "Për ta zgjidhur këtë problem, sigurohuni që po përdorni një shërbim gjeolokalizimi GeoIP me një bazë të dhënash GeoIP qytetesh. Nëse kjo nuk e zgjidh problemin tuaj, atëherë ka mundësi (edhe pse zor) që vizitat tuaja të kenë adresa IP që nuk gjeolokalizohen dot."
+ }
+}
\ No newline at end of file
diff --git a/lang/sr.json b/lang/sr.json
new file mode 100644
index 0000000..7d19baa
--- /dev/null
+++ b/lang/sr.json
@@ -0,0 +1,25 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Ovaj dodatak donosi vidžete Mapa posetilaca i Mapa u realnom vremenu. Zahteva UserCountry dodatak.",
+ "AndNOthers": "i %s ostalih",
+ "Cities": "Gradovi",
+ "Countries": "Države",
+ "DaysAgo": "pre %s dana",
+ "GoalConversions": "%s ispunjenih ciljeva",
+ "HoursAgo": "pre %s sati",
+ "map": "mapa",
+ "MinutesAgo": "pre %s minuta",
+ "None": "Ništa",
+ "NoVisit": "Nema poseta",
+ "RealTimeMap": "Mapa u realnom vremenu",
+ "Regions": "Regioni",
+ "Searches": "%s pretraga",
+ "SecondsAgo": "pre %s sekundi",
+ "ShowingVisits": "Geolocirane posete od poslednjih",
+ "Unlocated": "%s<\/b> %p od poseta sa %c nije moguće geolocirati.",
+ "VisitorMap": "Mapa posetilaca",
+ "WorldWide": "Ceo svet",
+ "WithUnknownRegion": "%s sa nepoznatim regionom",
+ "WithUnknownCity": "%s sa nepoznatim gradom"
+ }
+}
\ No newline at end of file
diff --git a/lang/sv.json b/lang/sv.json
new file mode 100644
index 0000000..5016dba
--- /dev/null
+++ b/lang/sv.json
@@ -0,0 +1,27 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Denna plugin ger dig widgetarna besökskarta och realtidskarta. Notera: Kräver aktiverad UserCountry-plugin.",
+ "AndNOthers": "och %s andra",
+ "Cities": "Städer",
+ "Countries": "Länder",
+ "DaysAgo": "%s dagar sedan",
+ "GoalConversions": "%s målomvandlingar",
+ "HoursAgo": "%s timmar sedan",
+ "map": "karta",
+ "MinutesAgo": "%s minuter sedan",
+ "None": "Ingen",
+ "NoVisit": "Inga besök",
+ "RealTimeMap": "Realtidskarta",
+ "Regions": "Regioner",
+ "Searches": "%s sökningar",
+ "SecondsAgo": "%s sekunder sedan",
+ "ShowingVisits": "Geolokaliserade besök de senaste",
+ "Unlocated": "%s<\/b> %p av besöken från %c kunde inte geolokaliseras.",
+ "VisitorMap": "Besökskarta",
+ "WorldWide": "Hela världen",
+ "WithUnknownRegion": "%s med okänd region",
+ "WithUnknownCity": "%s med okänd stad",
+ "NoVisitsInfo": "Det finns inga besök som visas för tillfället, eftersom inget besök för denna period har rätt geografisk platsinformation (latitud och longitud).",
+ "NoVisitsInfo2": "För att lösa detta problem se till att du använder en GeoIP leverantör med en databas över städer. Om det inte löser problemet är det möjligt (men osannolikt) att dina besök har IP-adresser som inte kan geopositioneras."
+ }
+}
\ No newline at end of file
diff --git a/lang/te.json b/lang/te.json
new file mode 100644
index 0000000..bad005a
--- /dev/null
+++ b/lang/te.json
@@ -0,0 +1,5 @@
+{
+ "UserCountryMapIslandora": {
+ "map": "పటం"
+ }
+}
\ No newline at end of file
diff --git a/lang/th.json b/lang/th.json
new file mode 100644
index 0000000..d77c20d
--- /dev/null
+++ b/lang/th.json
@@ -0,0 +1,5 @@
+{
+ "UserCountryMapIslandora": {
+ "map": "แผนที่"
+ }
+}
\ No newline at end of file
diff --git a/lang/tl.json b/lang/tl.json
new file mode 100644
index 0000000..c9c2c4d
--- /dev/null
+++ b/lang/tl.json
@@ -0,0 +1,24 @@
+{
+ "UserCountryMapIslandora": {
+ "AndNOthers": "at %s iba",
+ "Cities": "Lungsod",
+ "Countries": "Mga Bansa",
+ "DaysAgo": "araw %s na ang nakalipas",
+ "GoalConversions": "Mga %s goal conversion",
+ "HoursAgo": "oras %s na ang nakalipas",
+ "map": "mapa",
+ "MinutesAgo": "%s minuto ang nakalipas",
+ "None": "Wala",
+ "NoVisit": "walang bumisita",
+ "RealTimeMap": "Real-time Map",
+ "Regions": "Mga Rehiyon",
+ "Searches": "%s searches",
+ "SecondsAgo": "segundo %s na ang nakalipas",
+ "ShowingVisits": "Geo-located na pagbisita ng huling",
+ "Unlocated": " %s %p sa mga pagbisita mula sa %c ay hindi pwedeng i-geolocated.",
+ "VisitorMap": "Mapa ng bumisita",
+ "WorldWide": "World-Wide",
+ "WithUnknownRegion": "%s na may hindi kilalang rehiyon",
+ "WithUnknownCity": "%s hindi kilalang lungsod"
+ }
+}
\ No newline at end of file
diff --git a/lang/tr.json b/lang/tr.json
new file mode 100644
index 0000000..2a1d264
--- /dev/null
+++ b/lang/tr.json
@@ -0,0 +1,27 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Bu uygulama eki Ziyaretçi Haritası ve Gerçek Zamanlı Harita gereçlerini görüntüler. Not: Kullanıcı Ülkesi uygulama ekinin etkinleştirilmiş olması gerekir.",
+ "AndNOthers": "ve %s diğer",
+ "Cities": "İller",
+ "Countries": "Ülkeler",
+ "DaysAgo": "%s gün önce",
+ "GoalConversions": "%s hedef tutturma",
+ "HoursAgo": "%s saat önce",
+ "map": "harita",
+ "MinutesAgo": "%s dakika önce",
+ "None": "Yok",
+ "NoVisit": "Henüz bir ziyaret yok",
+ "RealTimeMap": "Gerçek Zamanlı Harita",
+ "Regions": "Bölgeler",
+ "Searches": "%s arama",
+ "SecondsAgo": "%s saniye önce",
+ "ShowingVisits": "Son dönemdeki ziyaret coğrafi konumları",
+ "Unlocated": "%c üzerinden %s<\/b> %p ziyaretin coğrafi konumu belirlenemedi.",
+ "VisitorMap": "Ziyaretçi Haritası",
+ "WorldWide": "Dünya Geneli",
+ "WithUnknownRegion": "%s ziyaretin bölgesi bilinmiyor",
+ "WithUnknownCity": "%s ziyaretin ili bilinmiyor",
+ "NoVisitsInfo": "Bu aralıkta doğru coğrafi konum bilgilerine (enlem ve boylam) sahip herhangi bir ziyaret olmadığından, şu anda görüntülenecek bir ziyaret yok.",
+ "NoVisitsInfo2": "Bu sorunu çözmek için GeoIP il veritabanı ile bir GeoIP hizmeti sağlayıcısını kullandığınızdan emin olun. Sorun çözülmez ise (pek olası olmamakla birlikte) ziyaretçilerinizin IP adresleri coğrafi kodlaması yapılamayan adreslerdir."
+ }
+}
\ No newline at end of file
diff --git a/lang/uk.json b/lang/uk.json
new file mode 100644
index 0000000..5fa33f2
--- /dev/null
+++ b/lang/uk.json
@@ -0,0 +1,25 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "Цей плагін надає віджет відображення відвідувачів на карті в реальному часі. Примітка: вимагає активації плагіну UserCountry.",
+ "AndNOthers": "та %s інших",
+ "Cities": "Міста",
+ "Countries": "Країни",
+ "DaysAgo": "%s днів назад",
+ "GoalConversions": "%s цілей досягнуто",
+ "HoursAgo": "%s годин тому",
+ "map": "мапа",
+ "MinutesAgo": "%s хвилин тому",
+ "None": "Немає",
+ "NoVisit": "Без відвідувань",
+ "RealTimeMap": "Мапа в реальному часі",
+ "Regions": "Регіони",
+ "Searches": "%s пошукових запитів",
+ "SecondsAgo": "%s секунд тому",
+ "ShowingVisits": "Останні геолокаційні відвідування",
+ "Unlocated": "%s<\/b> %p відвідування з %c не можуть бути геолокалізованни.",
+ "VisitorMap": "Мапа відвідувань",
+ "WorldWide": "Весь світ",
+ "WithUnknownRegion": "%s з невідомим регіоном",
+ "WithUnknownCity": "%s з невідомим містом"
+ }
+}
\ No newline at end of file
diff --git a/lang/vi.json b/lang/vi.json
new file mode 100644
index 0000000..a3c908f
--- /dev/null
+++ b/lang/vi.json
@@ -0,0 +1,22 @@
+{
+ "UserCountryMapIslandora": {
+ "AndNOthers": "và %s khác",
+ "Cities": "Các thành phố",
+ "Countries": "Các quốc gia",
+ "DaysAgo": "%s ngày cách đây",
+ "GoalConversions": "%s các chuyển đổi mục tiêu",
+ "HoursAgo": "%s giờ cách đây",
+ "map": "Bản đồ",
+ "MinutesAgo": "%s phút cách đây",
+ "None": "Không có gì",
+ "NoVisit": "Không có truy cập nào",
+ "RealTimeMap": "Bản đồ thời gian thực",
+ "Regions": "Các vùng",
+ "Searches": "%s tìm kiếm",
+ "SecondsAgo": "%s giây cách đây",
+ "ShowingVisits": "Định vị lượt truy cập cuối cùng",
+ "Unlocated": "%s<\/b> %p các lượt truy cập từ %c có thể không được định vị.",
+ "VisitorMap": "Bản đồ khách truy cập",
+ "WorldWide": "Khắp thế giới"
+ }
+}
\ No newline at end of file
diff --git a/lang/zh-cn.json b/lang/zh-cn.json
new file mode 100644
index 0000000..0373bf8
--- /dev/null
+++ b/lang/zh-cn.json
@@ -0,0 +1,25 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "这个插件提供了访客地图和实时地图的小工具。注意:需要激活UserCountry插件。",
+ "AndNOthers": "和 %s 其它",
+ "Cities": "城市",
+ "Countries": "国家",
+ "DaysAgo": "%s 天前",
+ "GoalConversions": "%s 目标转化",
+ "HoursAgo": "%s 小时前",
+ "map": "地图",
+ "MinutesAgo": "%s 分钟前",
+ "None": "无",
+ "NoVisit": "没有访问",
+ "RealTimeMap": "实时地图",
+ "Regions": "地区",
+ "Searches": "%s 次搜索",
+ "SecondsAgo": "%s 秒前",
+ "ShowingVisits": "最后访客地理位置",
+ "Unlocated": "%s<\/b> %p 的访问来自 %c 无法定位地理位置。",
+ "VisitorMap": "访客地图",
+ "WorldWide": "全世界",
+ "WithUnknownRegion": "%s未知区域",
+ "WithUnknownCity": "%s未知城市"
+ }
+}
\ No newline at end of file
diff --git a/lang/zh-tw.json b/lang/zh-tw.json
new file mode 100644
index 0000000..a54ec2f
--- /dev/null
+++ b/lang/zh-tw.json
@@ -0,0 +1,27 @@
+{
+ "UserCountryMapIslandora": {
+ "PluginDescription": "這個外掛提供訪客地圖和即時地圖外掛。注意:需要啟用 UserCountry 外掛。",
+ "AndNOthers": "和其他 %s 人",
+ "Cities": "城市",
+ "Countries": "國家",
+ "DaysAgo": "%s 天前",
+ "GoalConversions": "%s 個目標轉換",
+ "HoursAgo": "%s 小時前",
+ "map": "地圖",
+ "MinutesAgo": "%s 分前",
+ "None": "無",
+ "NoVisit": "沒有資料",
+ "RealTimeMap": "即時地圖",
+ "Regions": "地區",
+ "Searches": "%s 個搜尋次數",
+ "SecondsAgo": "%s 秒前",
+ "ShowingVisits": "訪客地理位置從過去的",
+ "Unlocated": "來自 %c 的訪客 %s<\/b> %p 無法定位地理位置。",
+ "VisitorMap": "訪客分佈地圖",
+ "WorldWide": "全球",
+ "WithUnknownRegion": "%s 個未知地區",
+ "WithUnknownCity": "%s 個未知城市",
+ "NoVisitsInfo": "由於這段期間內沒有任何包含正確地理位置資訊(經度、緯度)的訪問,因此目前沒有顯示任何訪問。",
+ "NoVisitsInfo2": "要解決這個問題,確定你正在使用包含 GeoIP 程式資料庫的 GeoIP 地理位置供應商。如果這沒有解決你的問題,那麼有可能(雖然不太可能)是你的訪客使用了無法被定位的 IP 位址。"
+ }
+}
\ No newline at end of file
diff --git a/plugin.json b/plugin.json
new file mode 100644
index 0000000..f390d88
--- /dev/null
+++ b/plugin.json
@@ -0,0 +1,20 @@
+{
+ "name": "UserCountryMapIslandora",
+ "version": "1.0.0",
+ "description": "Custom Map with no Popups, 90% based on UserCountryMap",
+ "keywords": ["Map", "Embed"],
+ "license": "GPL v3+",
+ "homepage": "http://piwik.org",
+ "require": {
+ "piwik": ">=3.0.0-b1,<4.0.0-b1"
+ },
+ "support": {
+ "source": "https://github.com/diegopino/plugin-UserCountryMapIslandora"
+ },
+ "authors": [
+ {
+ "name": "Diego Pino",
+ "email": "dpino@metro.org",
+ }
+ ]
+}
diff --git a/stylesheets/map.css b/stylesheets/map.css
new file mode 100644
index 0000000..6bd3a73
--- /dev/null
+++ b/stylesheets/map.css
@@ -0,0 +1,83 @@
+/*
+ * Stylesheets for Kartograph map
+ */
+
+.UserCountryMapIslandora_map svg path {
+ stroke-linejoin: round;
+}
+
+.UserCountryMapIslandora svg .countries {
+ cursor: pointer;
+ stroke-width: 0.5px;
+ stroke: #545C6D;
+}
+
+.UserCountryMapIslandora svg .context {
+ stroke: #BBBBBB;
+ fill: #F6F5F3;
+ stroke-width: 0.5px;
+}
+
+.UserCountryMapIslandora svg .context-clickable {
+ cursor: pointer;
+ stroke: #BBBBBB;
+ fill: #F2F1ED;
+ stroke-width: 0.5px;
+}
+
+.UserCountryMapIslandora svg .context-clickable:hover {
+ fill: #E4E2D7;
+}
+
+.UserCountryMapIslandora svg .regionBG {
+ stroke-width: 6px;
+ stroke: #fff;
+ fill: none;
+}
+
+.UUserCountryMapIslandora svg .regionBG-fill {
+ stroke: #555;
+ stroke-width: 0.2px;
+ fill: #F6F5F3;
+}
+
+.UserCountryMapIslandora svg .regionBG-3 {
+ stroke: #ccc;
+ fill: #F2F1ED;
+ stroke-width: 1px;
+}
+
+.UUserCountryMapIslandora svg .countryBG {
+ stroke: #fff;
+ fill: #fff;
+ stroke-width: 4px;
+}
+
+.UserCountryMapIslandora svg .regions {
+ stroke-width: 1px;
+}
+
+.UserCountryMapIslandora svg .regions2 {
+ stroke-width: 1px;
+ stroke: #aaa;
+ fill: #fff;
+}
+
+.UserCountryMapIslandora svg .countryLabelBg {
+ font-weight: bold;
+ font-size: 10px;
+ font-family: Arial, Verdana, Helvetica, sans-serif;
+ fill: #F6F5F3;
+ stroke: #F6F5F3;
+ stroke-width: 3px;
+ stroke-linejoin: round;
+ stroke-linecap: round;
+}
+
+.UserCountryMapIslandora svg .countryLabel {
+ font-weight: bold;
+ font-size: 10px;
+ font-family: Arial, Verdana, Helvetica, sans-serif;
+ fill: #808888;
+}
+
diff --git a/stylesheets/visitor-map.less b/stylesheets/visitor-map.less
new file mode 100644
index 0000000..6becb0c
--- /dev/null
+++ b/stylesheets/visitor-map.less
@@ -0,0 +1,239 @@
+.UserCountryMap-black {
+ position: absolute;
+ right: 0;
+ left: 0;
+ z-index: 900;
+ width: 1000px;
+ height: 1000px;
+ background: #D5D3C8;
+}
+
+.UserCountryMap .unlocatableCount {
+ font-size: 11px;
+ color: @color-silver-l60;
+}
+
+.UserCountryMap .loadingPiwik {
+ position: absolute !important;
+ top: 42% !important;
+ right: 10px !important;
+ left: 10px !important;
+ z-index: 100 !important;
+ display: block;
+ font-size: 12px;
+ color: #000;
+ vertical-align: middle !important;
+ text-align: center;
+ text-shadow: 0 0 5px #fff;
+}
+
+.tableIcon.inactiveIcon {
+ color: #99a;
+}
+
+.UserCountryMap .UserCountryMap-legend {
+ opacity: 0;
+}
+
+.UserCountryMap:hover .UserCountryMap-legend {
+ opacity: 1;
+}
+
+.UserCountryMap-overlay,
+.UserCountryMap-tooltip {
+ display: block;
+ position: absolute;
+ z-index: 40;
+}
+
+.UserCountryMap-overlay .content,
+.UserCountryMap-tooltip .content {
+ padding: 5px;
+ border-radius: 3px;
+ background: rgba(255, 255, 255, 0.9);
+}
+
+.UserCountryMap-title {
+ top: 5px;
+ left: 5px;
+}
+
+.UserCountryMap-legend {
+ right: 5px;
+ font-size: 9px;
+ bottom: 24px;
+}
+
+.UserCountryMap-info {
+ left: 5px;
+ font-size: 11px;
+ bottom: 60px;
+ max-width: 42%;
+}
+
+.UserCountryMap-info-btn {
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAA3NCSVQICAjb4U/gAAAAOVBMVEX///8AAAAAAABXV1dSUlKsrKzExMTd3d3V1dXp6end3d3p6enz8/P7+/v39/f///+vqZ6oopWUjH2LPulWAAAAE3RSTlMAESIzM2Z3mZmqqrvd7u7/////UUgTXgAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAAAYdEVYdENyZWF0aW9uIFRpbWUAMDMuMDEuMjAxM8rVeD8AAABnSURBVBiVhY/LFoAgCEQZ0p4W6f9/bIJ4slV3oTIeBoaICGADIAO8ibEwWn2IcwVovev7znqmCYRon9kEWUFvg3IysXyIXSil3fOvELupC9XUx7pQx/piDV1sVFLwMNF80sw97hj/AXRPCjtYdmhtAAAAAElFTkSuQmCC);
+ width: 16px;
+ height: 16px;
+ cursor: pointer;
+ left: 13px;
+ bottom: 40px;
+ position: absolute;
+ z-index: 700;
+ opacity: 0.9;
+}
+
+/* this should me moved to TableView css sometimes */
+.dataTableFooterIcons .inactiveIcon:hover {
+ background-color: #F2F1ED;
+}
+
+.dataTableFooterIcons .inactiveIcon {
+ cursor: default;
+}
+
+.dataTableFooterIcons .inactiveIcon img {
+ opacity: 0.3;
+ -moz-opacity: 0.3;
+ filter: alpha(opacity=3);
+}
+
+.mapWidgetStatus {
+ padding-bottom: 24px;
+}
+
+.widgetUserCountryMapvisitorMap .widgetTop .button {
+ z-index: 3;
+ position: relative;
+}
+
+.widgetUserCountryMapvisitorMap .widgetName {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+
+.widgetUserCountryMapvisitorMap.widgetHover .widgetName {
+ width: 75%;
+ overflow: hidden;
+}
+
+// visitor map colors
+.visitor-map[data-name=no-data-color] {
+ color: #E4E2D7;
+}
+
+.visitor-map[data-name=one-country-color] {
+ color: #CDDAEF;
+}
+
+.visitor-map[data-name=color-range-start-choropleth] {
+ color: #CDDAEF;
+}
+
+.visitor-map[data-name=color-range-start-normal] {
+ color: #385993;
+}
+
+.visitor-map[data-name=color-range-end-choropleth] {
+ color: #385993;
+}
+
+.visitor-map[data-name=color-range-end-normal] {
+ color: #385993;
+}
+
+.visitor-map[data-name=country-highlight-color] {
+ color: #f4f45b;
+}
+
+.visitor-map[data-name=country-selected-color] {
+ color: #f4f45b;
+}
+
+.visitor-map[data-name=unknown-region-fill-color] {
+ color: @theme-color-background-base;
+}
+
+.visitor-map[data-name=unknown-region-stroke-color] {
+ color: #bbb;
+}
+
+.visitor-map[data-name=region-stroke-color] {
+ color: #3C6FB6;
+}
+
+.visitor-map[data-name=region-selected-color] {
+ color: #f4f45b;
+}
+
+.visitor-map[data-name=region-highlight-color] {
+ color: #f4f45b;
+}
+
+.visitor-map[data-name=invisible-region-background] {
+ color: @theme-color-background-base;
+}
+
+.visitor-map[data-name=city-label-color] {
+ color: @theme-color-background-base;
+}
+
+.visitor-map[data-name=city-stroke-color] {
+ color: @theme-color-background-base;
+}
+
+.visitor-map[data-name=city-highlight-stroke-color] {
+ color: #000000;
+}
+
+.visitor-map[data-name=city-highlight-fill-color] {
+ color: #f4f45b;
+}
+
+.visitor-map[data-name=city-highlight-label-color] {
+ color: #000;
+}
+
+.visitor-map[data-name=city-label-fill-color] {
+ color: @theme-color-background-base;
+}
+
+.visitor-map[data-name=city-selected-color] {
+ color: #f4f45b;
+}
+
+.visitor-map[data-name=city-selected-label-color] {
+ color: #000;
+}
+
+.visitor-map[data-name=region-layer-stroke-color] {
+ color: #aaa;
+}
+
+.visitor-map[data-name=special-metrics-color-scale-1] {
+ color: #385993;
+}
+
+.visitor-map[data-name=special-metrics-color-scale-2] {
+ color: #385993;
+}
+
+.visitor-map[data-name=special-metrics-color-scale-3] {
+ color: #E87500;
+}
+
+.visitor-map[data-name=special-metrics-color-scale-4] {
+ color: #E87500;
+}
+
+.userCountryMapSelectCountry, .userCountryMapSelectMetrics {
+ float: right;
+ margin-right: 5px;
+ margin-bottom: 5px;
+ max-width: 10em;
+ font-size: 10px;
+}
+
+.ui-tooltip.qtip {
+ min-width: 100px;
+}
\ No newline at end of file
diff --git a/svg/AF.svg b/svg/AF.svg
new file mode 100644
index 0000000..02430b3
--- /dev/null
+++ b/svg/AF.svg
@@ -0,0 +1,2 @@
+
diff --git a/svg/AFG.svg b/svg/AFG.svg
new file mode 100644
index 0000000..1d90e28
--- /dev/null
+++ b/svg/AFG.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/AGO.svg b/svg/AGO.svg
new file mode 100644
index 0000000..74ae37c
--- /dev/null
+++ b/svg/AGO.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ALB.svg b/svg/ALB.svg
new file mode 100644
index 0000000..2812a5c
--- /dev/null
+++ b/svg/ALB.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ARE.svg b/svg/ARE.svg
new file mode 100644
index 0000000..0270a3c
--- /dev/null
+++ b/svg/ARE.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ARG.svg b/svg/ARG.svg
new file mode 100644
index 0000000..677c406
--- /dev/null
+++ b/svg/ARG.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ARM.svg b/svg/ARM.svg
new file mode 100644
index 0000000..5b42fa7
--- /dev/null
+++ b/svg/ARM.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/AS.svg b/svg/AS.svg
new file mode 100644
index 0000000..b425e8d
--- /dev/null
+++ b/svg/AS.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/AUS.svg b/svg/AUS.svg
new file mode 100644
index 0000000..2a919f5
--- /dev/null
+++ b/svg/AUS.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/AUT.svg b/svg/AUT.svg
new file mode 100644
index 0000000..4955787
--- /dev/null
+++ b/svg/AUT.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/AZE.svg b/svg/AZE.svg
new file mode 100644
index 0000000..f7fea03
--- /dev/null
+++ b/svg/AZE.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BDI.svg b/svg/BDI.svg
new file mode 100644
index 0000000..8cda2dc
--- /dev/null
+++ b/svg/BDI.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BEL.svg b/svg/BEL.svg
new file mode 100644
index 0000000..4b3a0f8
--- /dev/null
+++ b/svg/BEL.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/svg/BEN.svg b/svg/BEN.svg
new file mode 100644
index 0000000..10956f7
--- /dev/null
+++ b/svg/BEN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BFA.svg b/svg/BFA.svg
new file mode 100644
index 0000000..4e016e6
--- /dev/null
+++ b/svg/BFA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BGD.svg b/svg/BGD.svg
new file mode 100644
index 0000000..fa82fa1
--- /dev/null
+++ b/svg/BGD.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BGR.svg b/svg/BGR.svg
new file mode 100644
index 0000000..141ae02
--- /dev/null
+++ b/svg/BGR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BIH.svg b/svg/BIH.svg
new file mode 100644
index 0000000..ffe908f
--- /dev/null
+++ b/svg/BIH.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BLR.svg b/svg/BLR.svg
new file mode 100644
index 0000000..6c0004e
--- /dev/null
+++ b/svg/BLR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BLZ.svg b/svg/BLZ.svg
new file mode 100644
index 0000000..e118f1d
--- /dev/null
+++ b/svg/BLZ.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BOL.svg b/svg/BOL.svg
new file mode 100644
index 0000000..d29c426
--- /dev/null
+++ b/svg/BOL.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BRA.svg b/svg/BRA.svg
new file mode 100644
index 0000000..1e85137
--- /dev/null
+++ b/svg/BRA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BRB.svg b/svg/BRB.svg
new file mode 100644
index 0000000..2b7ef1f
--- /dev/null
+++ b/svg/BRB.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BRN.svg b/svg/BRN.svg
new file mode 100644
index 0000000..82361e5
--- /dev/null
+++ b/svg/BRN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BTN.svg b/svg/BTN.svg
new file mode 100644
index 0000000..4d6ba17
--- /dev/null
+++ b/svg/BTN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/BWA.svg b/svg/BWA.svg
new file mode 100644
index 0000000..f6557ba
--- /dev/null
+++ b/svg/BWA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/CAF.svg b/svg/CAF.svg
new file mode 100644
index 0000000..639ddc7
--- /dev/null
+++ b/svg/CAF.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/CAN.svg b/svg/CAN.svg
new file mode 100644
index 0000000..d946475
--- /dev/null
+++ b/svg/CAN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/CHE.svg b/svg/CHE.svg
new file mode 100644
index 0000000..f9990fb
--- /dev/null
+++ b/svg/CHE.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/CHL.svg b/svg/CHL.svg
new file mode 100644
index 0000000..b47bddb
--- /dev/null
+++ b/svg/CHL.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/CHN.svg b/svg/CHN.svg
new file mode 100644
index 0000000..e414fbb
--- /dev/null
+++ b/svg/CHN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/CIV.svg b/svg/CIV.svg
new file mode 100644
index 0000000..583a3d9
--- /dev/null
+++ b/svg/CIV.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/CMR.svg b/svg/CMR.svg
new file mode 100644
index 0000000..bb6905c
--- /dev/null
+++ b/svg/CMR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/COD.svg b/svg/COD.svg
new file mode 100644
index 0000000..46aba0a
--- /dev/null
+++ b/svg/COD.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/COG.svg b/svg/COG.svg
new file mode 100644
index 0000000..87606ea
--- /dev/null
+++ b/svg/COG.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/COL.svg b/svg/COL.svg
new file mode 100644
index 0000000..6cd0a80
--- /dev/null
+++ b/svg/COL.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/CRI.svg b/svg/CRI.svg
new file mode 100644
index 0000000..549ab9a
--- /dev/null
+++ b/svg/CRI.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/CUB.svg b/svg/CUB.svg
new file mode 100644
index 0000000..7eba9f6
--- /dev/null
+++ b/svg/CUB.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/CYP.svg b/svg/CYP.svg
new file mode 100644
index 0000000..2d6f4e9
--- /dev/null
+++ b/svg/CYP.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/CZE.svg b/svg/CZE.svg
new file mode 100644
index 0000000..c3ba77a
--- /dev/null
+++ b/svg/CZE.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/svg/DEU.svg b/svg/DEU.svg
new file mode 100644
index 0000000..dc2f760
--- /dev/null
+++ b/svg/DEU.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/svg/DJI.svg b/svg/DJI.svg
new file mode 100644
index 0000000..c52dee6
--- /dev/null
+++ b/svg/DJI.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/DMA.svg b/svg/DMA.svg
new file mode 100644
index 0000000..e8d51fe
--- /dev/null
+++ b/svg/DMA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/DNK.svg b/svg/DNK.svg
new file mode 100644
index 0000000..760d8d5
--- /dev/null
+++ b/svg/DNK.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/svg/DOM.svg b/svg/DOM.svg
new file mode 100644
index 0000000..1713a8d
--- /dev/null
+++ b/svg/DOM.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/DZA.svg b/svg/DZA.svg
new file mode 100644
index 0000000..1b4c966
--- /dev/null
+++ b/svg/DZA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ECU.svg b/svg/ECU.svg
new file mode 100644
index 0000000..25e490c
--- /dev/null
+++ b/svg/ECU.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/EGY.svg b/svg/EGY.svg
new file mode 100644
index 0000000..e0bff90
--- /dev/null
+++ b/svg/EGY.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ERI.svg b/svg/ERI.svg
new file mode 100644
index 0000000..42de412
--- /dev/null
+++ b/svg/ERI.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ESP.svg b/svg/ESP.svg
new file mode 100644
index 0000000..3cd091c
--- /dev/null
+++ b/svg/ESP.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/EST.svg b/svg/EST.svg
new file mode 100644
index 0000000..46342af
--- /dev/null
+++ b/svg/EST.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ETH.svg b/svg/ETH.svg
new file mode 100644
index 0000000..1cdf5d1
--- /dev/null
+++ b/svg/ETH.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/EU.svg b/svg/EU.svg
new file mode 100644
index 0000000..bed2b60
--- /dev/null
+++ b/svg/EU.svg
@@ -0,0 +1,2 @@
+
diff --git a/svg/FIN.svg b/svg/FIN.svg
new file mode 100644
index 0000000..fd6f395
--- /dev/null
+++ b/svg/FIN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/FJI.svg b/svg/FJI.svg
new file mode 100644
index 0000000..8f0c1d2
--- /dev/null
+++ b/svg/FJI.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/FRA.svg b/svg/FRA.svg
new file mode 100644
index 0000000..0a22bf3
--- /dev/null
+++ b/svg/FRA.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/svg/FRO.svg b/svg/FRO.svg
new file mode 100644
index 0000000..ddc6a76
--- /dev/null
+++ b/svg/FRO.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/GAB.svg b/svg/GAB.svg
new file mode 100644
index 0000000..1f00849
--- /dev/null
+++ b/svg/GAB.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/GBR.svg b/svg/GBR.svg
new file mode 100644
index 0000000..6485875
--- /dev/null
+++ b/svg/GBR.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/svg/GEO.svg b/svg/GEO.svg
new file mode 100644
index 0000000..58f6454
--- /dev/null
+++ b/svg/GEO.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/GHA.svg b/svg/GHA.svg
new file mode 100644
index 0000000..8828300
--- /dev/null
+++ b/svg/GHA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/GIN.svg b/svg/GIN.svg
new file mode 100644
index 0000000..c852f02
--- /dev/null
+++ b/svg/GIN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/GMB.svg b/svg/GMB.svg
new file mode 100644
index 0000000..5c9eddf
--- /dev/null
+++ b/svg/GMB.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/GNB.svg b/svg/GNB.svg
new file mode 100644
index 0000000..8e3e6df
--- /dev/null
+++ b/svg/GNB.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/GNQ.svg b/svg/GNQ.svg
new file mode 100644
index 0000000..f71be08
--- /dev/null
+++ b/svg/GNQ.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/GRC.svg b/svg/GRC.svg
new file mode 100644
index 0000000..f41f4f4
--- /dev/null
+++ b/svg/GRC.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/GRL.svg b/svg/GRL.svg
new file mode 100644
index 0000000..ce1d349
--- /dev/null
+++ b/svg/GRL.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/GTM.svg b/svg/GTM.svg
new file mode 100644
index 0000000..9279c25
--- /dev/null
+++ b/svg/GTM.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/GUY.svg b/svg/GUY.svg
new file mode 100644
index 0000000..0d513e1
--- /dev/null
+++ b/svg/GUY.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/HND.svg b/svg/HND.svg
new file mode 100644
index 0000000..e7f480a
--- /dev/null
+++ b/svg/HND.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/HRV.svg b/svg/HRV.svg
new file mode 100644
index 0000000..ab731b2
--- /dev/null
+++ b/svg/HRV.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/HTI.svg b/svg/HTI.svg
new file mode 100644
index 0000000..0a4c8eb
--- /dev/null
+++ b/svg/HTI.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/HUN.svg b/svg/HUN.svg
new file mode 100644
index 0000000..8e136d2
--- /dev/null
+++ b/svg/HUN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/IDN.svg b/svg/IDN.svg
new file mode 100644
index 0000000..19965e4
--- /dev/null
+++ b/svg/IDN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/IND.svg b/svg/IND.svg
new file mode 100644
index 0000000..8607b7e
--- /dev/null
+++ b/svg/IND.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/IRL.svg b/svg/IRL.svg
new file mode 100644
index 0000000..36baa2d
--- /dev/null
+++ b/svg/IRL.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/IRN.svg b/svg/IRN.svg
new file mode 100644
index 0000000..714f6e9
--- /dev/null
+++ b/svg/IRN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/IRQ.svg b/svg/IRQ.svg
new file mode 100644
index 0000000..deeeb41
--- /dev/null
+++ b/svg/IRQ.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ISL.svg b/svg/ISL.svg
new file mode 100644
index 0000000..686c5ba
--- /dev/null
+++ b/svg/ISL.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ISR.svg b/svg/ISR.svg
new file mode 100644
index 0000000..056cf07
--- /dev/null
+++ b/svg/ISR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ITA.svg b/svg/ITA.svg
new file mode 100644
index 0000000..a2d0317
--- /dev/null
+++ b/svg/ITA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/JAM.svg b/svg/JAM.svg
new file mode 100644
index 0000000..5fa702c
--- /dev/null
+++ b/svg/JAM.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/JOR.svg b/svg/JOR.svg
new file mode 100644
index 0000000..1e65f8d
--- /dev/null
+++ b/svg/JOR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/JPN.svg b/svg/JPN.svg
new file mode 100644
index 0000000..b5cbd9a
--- /dev/null
+++ b/svg/JPN.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/svg/KAZ.svg b/svg/KAZ.svg
new file mode 100644
index 0000000..1afb67e
--- /dev/null
+++ b/svg/KAZ.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/KEN.svg b/svg/KEN.svg
new file mode 100644
index 0000000..e9e6ba8
--- /dev/null
+++ b/svg/KEN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/KGZ.svg b/svg/KGZ.svg
new file mode 100644
index 0000000..155b179
--- /dev/null
+++ b/svg/KGZ.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/KHM.svg b/svg/KHM.svg
new file mode 100644
index 0000000..4a7c2db
--- /dev/null
+++ b/svg/KHM.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/KOR.svg b/svg/KOR.svg
new file mode 100644
index 0000000..93348e0
--- /dev/null
+++ b/svg/KOR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/KWT.svg b/svg/KWT.svg
new file mode 100644
index 0000000..8493dda
--- /dev/null
+++ b/svg/KWT.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/LAO.svg b/svg/LAO.svg
new file mode 100644
index 0000000..c029e74
--- /dev/null
+++ b/svg/LAO.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/LBN.svg b/svg/LBN.svg
new file mode 100644
index 0000000..aebb292
--- /dev/null
+++ b/svg/LBN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/LBR.svg b/svg/LBR.svg
new file mode 100644
index 0000000..bd42df5
--- /dev/null
+++ b/svg/LBR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/LBY.svg b/svg/LBY.svg
new file mode 100644
index 0000000..7a471af
--- /dev/null
+++ b/svg/LBY.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/LKA.svg b/svg/LKA.svg
new file mode 100644
index 0000000..4ff6455
--- /dev/null
+++ b/svg/LKA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/LSO.svg b/svg/LSO.svg
new file mode 100644
index 0000000..7c6b211
--- /dev/null
+++ b/svg/LSO.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/LTU.svg b/svg/LTU.svg
new file mode 100644
index 0000000..65e6efd
--- /dev/null
+++ b/svg/LTU.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/LUX.svg b/svg/LUX.svg
new file mode 100644
index 0000000..da81e22
--- /dev/null
+++ b/svg/LUX.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/LVA.svg b/svg/LVA.svg
new file mode 100644
index 0000000..b71dd3e
--- /dev/null
+++ b/svg/LVA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/MAR.svg b/svg/MAR.svg
new file mode 100644
index 0000000..3ed5e22
--- /dev/null
+++ b/svg/MAR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/MDA.svg b/svg/MDA.svg
new file mode 100644
index 0000000..c7669c4
--- /dev/null
+++ b/svg/MDA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/MDG.svg b/svg/MDG.svg
new file mode 100644
index 0000000..f6dc836
--- /dev/null
+++ b/svg/MDG.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/MEX.svg b/svg/MEX.svg
new file mode 100644
index 0000000..d7bc895
--- /dev/null
+++ b/svg/MEX.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/MKD.svg b/svg/MKD.svg
new file mode 100644
index 0000000..3f4c7f0
--- /dev/null
+++ b/svg/MKD.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/MLI.svg b/svg/MLI.svg
new file mode 100644
index 0000000..687f25b
--- /dev/null
+++ b/svg/MLI.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/MMR.svg b/svg/MMR.svg
new file mode 100644
index 0000000..4cb5346
--- /dev/null
+++ b/svg/MMR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/MNE.svg b/svg/MNE.svg
new file mode 100644
index 0000000..1f993bb
--- /dev/null
+++ b/svg/MNE.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/MNG.svg b/svg/MNG.svg
new file mode 100644
index 0000000..6db1d54
--- /dev/null
+++ b/svg/MNG.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/MOZ.svg b/svg/MOZ.svg
new file mode 100644
index 0000000..a6b4e3e
--- /dev/null
+++ b/svg/MOZ.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/MRT.svg b/svg/MRT.svg
new file mode 100644
index 0000000..7e2ccfd
--- /dev/null
+++ b/svg/MRT.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/MWI.svg b/svg/MWI.svg
new file mode 100644
index 0000000..bcdff56
--- /dev/null
+++ b/svg/MWI.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/MYS.svg b/svg/MYS.svg
new file mode 100644
index 0000000..0d3fd84
--- /dev/null
+++ b/svg/MYS.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/NA.svg b/svg/NA.svg
new file mode 100644
index 0000000..e119622
--- /dev/null
+++ b/svg/NA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/NAM.svg b/svg/NAM.svg
new file mode 100644
index 0000000..e54144f
--- /dev/null
+++ b/svg/NAM.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/NCL.svg b/svg/NCL.svg
new file mode 100644
index 0000000..ebe6b62
--- /dev/null
+++ b/svg/NCL.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/NER.svg b/svg/NER.svg
new file mode 100644
index 0000000..c196f39
--- /dev/null
+++ b/svg/NER.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/NFK.svg b/svg/NFK.svg
new file mode 100644
index 0000000..12cf59f
--- /dev/null
+++ b/svg/NFK.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/NGA.svg b/svg/NGA.svg
new file mode 100644
index 0000000..9f20cdb
--- /dev/null
+++ b/svg/NGA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/NIC.svg b/svg/NIC.svg
new file mode 100644
index 0000000..802241c
--- /dev/null
+++ b/svg/NIC.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/NLD.svg b/svg/NLD.svg
new file mode 100644
index 0000000..0b6e814
--- /dev/null
+++ b/svg/NLD.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/NOR.svg b/svg/NOR.svg
new file mode 100644
index 0000000..51d741e
--- /dev/null
+++ b/svg/NOR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/NPL.svg b/svg/NPL.svg
new file mode 100644
index 0000000..4ab700c
--- /dev/null
+++ b/svg/NPL.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/NZL.svg b/svg/NZL.svg
new file mode 100644
index 0000000..ada46d9
--- /dev/null
+++ b/svg/NZL.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/svg/OC.svg b/svg/OC.svg
new file mode 100644
index 0000000..67efc78
--- /dev/null
+++ b/svg/OC.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/OMN.svg b/svg/OMN.svg
new file mode 100644
index 0000000..5b05bbe
--- /dev/null
+++ b/svg/OMN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/PAK.svg b/svg/PAK.svg
new file mode 100644
index 0000000..6597de8
--- /dev/null
+++ b/svg/PAK.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/PAN.svg b/svg/PAN.svg
new file mode 100644
index 0000000..04d4ce4
--- /dev/null
+++ b/svg/PAN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/PER.svg b/svg/PER.svg
new file mode 100644
index 0000000..c03b973
--- /dev/null
+++ b/svg/PER.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/PHL.svg b/svg/PHL.svg
new file mode 100644
index 0000000..e656c66
--- /dev/null
+++ b/svg/PHL.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/PNG.svg b/svg/PNG.svg
new file mode 100644
index 0000000..cba3c65
--- /dev/null
+++ b/svg/PNG.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/POL.svg b/svg/POL.svg
new file mode 100644
index 0000000..d6411c2
--- /dev/null
+++ b/svg/POL.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/svg/PRK.svg b/svg/PRK.svg
new file mode 100644
index 0000000..6f25e7a
--- /dev/null
+++ b/svg/PRK.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/PRT.svg b/svg/PRT.svg
new file mode 100644
index 0000000..f24d9fc
--- /dev/null
+++ b/svg/PRT.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/PRY.svg b/svg/PRY.svg
new file mode 100644
index 0000000..5f919bb
--- /dev/null
+++ b/svg/PRY.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/QAT.svg b/svg/QAT.svg
new file mode 100644
index 0000000..482f9eb
--- /dev/null
+++ b/svg/QAT.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ROU.svg b/svg/ROU.svg
new file mode 100644
index 0000000..4762a69
--- /dev/null
+++ b/svg/ROU.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/RUS.svg b/svg/RUS.svg
new file mode 100644
index 0000000..6f53335
--- /dev/null
+++ b/svg/RUS.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/RWA.svg b/svg/RWA.svg
new file mode 100644
index 0000000..bdebc08
--- /dev/null
+++ b/svg/RWA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SA.svg b/svg/SA.svg
new file mode 100644
index 0000000..7d7a587
--- /dev/null
+++ b/svg/SA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SAU.svg b/svg/SAU.svg
new file mode 100644
index 0000000..a294832
--- /dev/null
+++ b/svg/SAU.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SDN.svg b/svg/SDN.svg
new file mode 100644
index 0000000..decf7b2
--- /dev/null
+++ b/svg/SDN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SEN.svg b/svg/SEN.svg
new file mode 100644
index 0000000..d47af16
--- /dev/null
+++ b/svg/SEN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SLB.svg b/svg/SLB.svg
new file mode 100644
index 0000000..eab488f
--- /dev/null
+++ b/svg/SLB.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SLE.svg b/svg/SLE.svg
new file mode 100644
index 0000000..1630e18
--- /dev/null
+++ b/svg/SLE.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SLV.svg b/svg/SLV.svg
new file mode 100644
index 0000000..51001f2
--- /dev/null
+++ b/svg/SLV.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SOM.svg b/svg/SOM.svg
new file mode 100644
index 0000000..0b363e0
--- /dev/null
+++ b/svg/SOM.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SRB.svg b/svg/SRB.svg
new file mode 100644
index 0000000..36b6e8d
--- /dev/null
+++ b/svg/SRB.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SSD.svg b/svg/SSD.svg
new file mode 100644
index 0000000..d1b200c
--- /dev/null
+++ b/svg/SSD.svg
@@ -0,0 +1,2 @@
+
diff --git a/svg/SUR.svg b/svg/SUR.svg
new file mode 100644
index 0000000..9eca3f1
--- /dev/null
+++ b/svg/SUR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SVK.svg b/svg/SVK.svg
new file mode 100644
index 0000000..9df27fd
--- /dev/null
+++ b/svg/SVK.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SVN.svg b/svg/SVN.svg
new file mode 100644
index 0000000..30c0d83
--- /dev/null
+++ b/svg/SVN.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/svg/SWE.svg b/svg/SWE.svg
new file mode 100644
index 0000000..c67a194
--- /dev/null
+++ b/svg/SWE.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SWZ.svg b/svg/SWZ.svg
new file mode 100644
index 0000000..e21b25d
--- /dev/null
+++ b/svg/SWZ.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/SYR.svg b/svg/SYR.svg
new file mode 100644
index 0000000..c3f99cf
--- /dev/null
+++ b/svg/SYR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/TCD.svg b/svg/TCD.svg
new file mode 100644
index 0000000..888ca01
--- /dev/null
+++ b/svg/TCD.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/TGO.svg b/svg/TGO.svg
new file mode 100644
index 0000000..816a644
--- /dev/null
+++ b/svg/TGO.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/THA.svg b/svg/THA.svg
new file mode 100644
index 0000000..e42fb46
--- /dev/null
+++ b/svg/THA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/TJK.svg b/svg/TJK.svg
new file mode 100644
index 0000000..e7a1ca3
--- /dev/null
+++ b/svg/TJK.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/TKM.svg b/svg/TKM.svg
new file mode 100644
index 0000000..ab60c5c
--- /dev/null
+++ b/svg/TKM.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/TLS.svg b/svg/TLS.svg
new file mode 100644
index 0000000..e1c22a0
--- /dev/null
+++ b/svg/TLS.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/TTO.svg b/svg/TTO.svg
new file mode 100644
index 0000000..6c59789
--- /dev/null
+++ b/svg/TTO.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/TUN.svg b/svg/TUN.svg
new file mode 100644
index 0000000..f395f1f
--- /dev/null
+++ b/svg/TUN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/TUR.svg b/svg/TUR.svg
new file mode 100644
index 0000000..178c296
--- /dev/null
+++ b/svg/TUR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/TWN.svg b/svg/TWN.svg
new file mode 100644
index 0000000..b0a2e25
--- /dev/null
+++ b/svg/TWN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/TZA.svg b/svg/TZA.svg
new file mode 100644
index 0000000..2d1436b
--- /dev/null
+++ b/svg/TZA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/UGA.svg b/svg/UGA.svg
new file mode 100644
index 0000000..cdb157a
--- /dev/null
+++ b/svg/UGA.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/UKR.svg b/svg/UKR.svg
new file mode 100644
index 0000000..7569efb
--- /dev/null
+++ b/svg/UKR.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/URY.svg b/svg/URY.svg
new file mode 100644
index 0000000..ee27c7d
--- /dev/null
+++ b/svg/URY.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/USA.svg b/svg/USA.svg
new file mode 100644
index 0000000..586c550
--- /dev/null
+++ b/svg/USA.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/svg/UZB.svg b/svg/UZB.svg
new file mode 100644
index 0000000..9463718
--- /dev/null
+++ b/svg/UZB.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/VEN.svg b/svg/VEN.svg
new file mode 100644
index 0000000..03cd368
--- /dev/null
+++ b/svg/VEN.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/VNM.svg b/svg/VNM.svg
new file mode 100644
index 0000000..df77e0a
--- /dev/null
+++ b/svg/VNM.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/VUT.svg b/svg/VUT.svg
new file mode 100644
index 0000000..a77b3b0
--- /dev/null
+++ b/svg/VUT.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/YEM.svg b/svg/YEM.svg
new file mode 100644
index 0000000..6e3b561
--- /dev/null
+++ b/svg/YEM.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ZAF.svg b/svg/ZAF.svg
new file mode 100644
index 0000000..ab2d6e8
--- /dev/null
+++ b/svg/ZAF.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ZMB.svg b/svg/ZMB.svg
new file mode 100644
index 0000000..542bb26
--- /dev/null
+++ b/svg/ZMB.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/ZWE.svg b/svg/ZWE.svg
new file mode 100644
index 0000000..5f0ac14
--- /dev/null
+++ b/svg/ZWE.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/tmp.svg b/svg/tmp.svg
new file mode 100644
index 0000000..fd6f395
--- /dev/null
+++ b/svg/tmp.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/svg/world.svg b/svg/world.svg
new file mode 100644
index 0000000..8929e6a
--- /dev/null
+++ b/svg/world.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/templates/visitorMap.twig b/templates/visitorMap.twig
new file mode 100644
index 0000000..66f6a5c
--- /dev/null
+++ b/templates/visitorMap.twig
@@ -0,0 +1,106 @@
+
+
+{% if not noData %}
+
+
+{% endif %}