Skip to content
Extraits de code Groupes Projets
visitor-map.js 54,3 ko
Newer Older
  • Learn to ignore specific revisions
  • Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
    // # UserCountryMap
    // define a global scope
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    window.UserCountryMap = {};
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    UserCountryMap.run = function(config) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        var map = $K.map('#UserCountryMap_map'),
            main = $('#UserCountryMap_container'),
    
            worldTotalVisits = 0,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            width = main.width();
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        UserCountryMap.config = config;
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
        UserCountryMap.config.noDataColor = '#E4E2D7';
    
        UserCountryMap.widget = $('#widgetUserCountryMapvisitorMap').parent();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        window.__userCountryMap = map;
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function _reportParams(module, action, countryFilter) {
            var params = $.extend(UserCountryMap.reqParams, {
                module: 'API',
                method: 'API.getProcessedReport',
                apiModule: module,
                apiAction: action,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                filter_limit: -1,
                enable_filter_excludelowpop: 1
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            });
            if (countryFilter) {
                $.extend(params, {
                    filter_column: 'country',
                    filter_sort_column: 'nb_visits',
                    filter_pattern: countryFilter
                });
            }
            return params;
        }
    
    
        function minmax(values) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            values = values.sort(function(a,b) { return Number(a) - Number(b); });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            return {
                min: values[0],
                max: values[values.length-1],
                median: values[Math.floor(values.length*0.5)],
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                p33: values[Math.floor(values.length*0.33)],
                p66: values[Math.floor(values.length*0.66)],
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                p90: values[Math.floor(values.length*0.9)]
            };
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * resizes the map
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function onResize() {
            var ratio, w, h;
            ratio = map.viewAB.width / map.viewAB.height;
            w = map.container.width();
            h = w / ratio;
            map.container.height(h-2);
            map.resize(w, h);
    
    
            if (w < 355) $('.tableIcon span').hide();
            else $('.tableIcon span').show();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function formatNumber(v) {
            v = Number(v);
            return v > 1000000 ? (v/1000000).toFixed(1) + 'm' :
                v > 1000 ? (v/1000).toFixed(1) + 'k' :
                v;
        }
    
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
        //
        // Since some metrics are transmitted in an non-numeric format like
        // "61.45%", we need to parse the numbers to make sure they can be
        // used for color scales etc. The parsed metrics will be stored as
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
        //
    
        function formatValueForTooltips(data, metric, id) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            var val = data[metric] % 1 === 0 || Number(data[metric]) != data[metric]  ? data[metric] : data[metric].toFixed(1),
                v = UserCountryMap._[metric].replace('%s', '<b>'+val+'</b>');
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            if (val == 1 && metric == 'nb_visits') v = UserCountryMap._.one_visit.replace('%s', '<b>'+val+'</b>');
    
    
            function avgTime(d) { return d['sum_visit_length'] / d['nb_visits']; }
    
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
            if (metric.substr(0, 3) == 'nb_' && metric != 'nb_actions_per_visit') {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                var total;
                if (id.length == 3) total = UserCountryMap.countriesByIso[id][metric];
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                else if (id == 'world') total = UserCountryMap._worldTotal;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                else {
                    total = 0;
                    $.each(UserCountryMap.countriesByIso, function(iso, country) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        if (UserCountryMap.ISO3toCONT[iso] == id) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            total += country[metric];
                        }
                    });
                }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                if (total) {
                    v += ' ('+formatPercentage(data[metric] / total)+')';
                }
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
            } else if (metric == 'avg_time_on_site') {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                v += '<br/> (over '+data.nb_visits+' visits)';
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
            }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            return v;
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function getColorScale(rows, metric, filter, choropleth) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
            var colscale;
    
            function addLegendItem(val) {
                var d = $('<div>'), r = $('<div>'), l = $('<div>'), v = formatNumber(val);
                d.css({ width: 17, height: 17, float: 'left', background: colscale.getColor(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);
            }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            var stats, values = [], id = UserCountryMap.lastSelected, c;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            $.each(rows, function(i, r) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                if (!$.isFunction(filter) || filter(r)) {
                    var v = quantify(r, metric);
                    if (!isNaN(v)) values.push(v);
                }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            });
    
            stats = minmax(values);
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            if (stats.min == stats.max) {
                colscale = { getColor: function() { return '#CDDAEF'; } };
                if (choropleth) {
                    $('.UserCountryMap-legend .content').html('').show();
                    addLegendItem(stats.min);
                }
                return colscale;
            }
    
            colscale = new chroma.ColorScale({
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                colors: [choropleth ? '#CDDAEF' : '#385993', '#385993'],
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                limits: chroma.limits(values, 'c', 4),
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                mode: 'hcl'
            });
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            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 = new chroma.ColorScale({
                        colors: ['#385993', '#385993','#E87500', '#E87500'],
                        limits: chroma.limits(rows, 'c', 5, 'curMetric', filter),
                        positions: [0, c, c+0.001, 1],
                        mode: 'hsl'
                    });
                }
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
            }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
            // a good place to update the legend, isn't it?
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            if (choropleth) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                $('.UserCountryMap-legend .content').html('').show();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                var itemExists = {};
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                $.each(chroma.limits(values, 'k', 3), function(i, v) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    if (itemExists[v]) return;
                    addLegendItem(v);
                    itemExists[v] = true;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                });
    
            } else {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                $('.UserCountryMap-legend .content').hide();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            return colscale;
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
        }
    
    
        function formatPercentage(val) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            if (val < 0.001) return '< 0.1%';
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
            return Math.round(1000 * val)/10 + '%';
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * 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(UserCountryMap._resizeTimer);
            UserCountryMap._resizeTimer = setTimeout(onResize, 300);
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function activateButton(btn) {
            $('#UserCountryMap-view-mode-buttons a').removeClass('activeIcon');
            btn.addClass('activeIcon');
            $('#UserCountryMap-activeItem').offset({ left: btn.offset().left });
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function initUserInterface() {
            // react to changes of country select
            $('#userCountryMapSelectCountry').change(function() {
                updateState($('#userCountryMapSelectCountry').val());
            });
    
    
            function zoomOut() {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                var t = UserCountryMap.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').click(zoomOut);
            $('#UserCountryMap_map').click(zoomOut);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
            // handle window resizes
            $(window).resize(onResizeLazy);
    
            // enable mertic changes
            $('#userCountryMapSelectMetrics').change(function() {
                updateState(UserCountryMap.lastSelected);
            });
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            // handle city button
            (function(btn) {
                btn.click(function() {
                    if (UserCountryMap.lastSelected.length == 3) {
                        if (UserCountryMap.mode != "city") {
                            UserCountryMap.mode = "city";
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            updateState(UserCountryMap.lastSelected);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        }
                    }
                });
            })($('#UserCountryMap-btn-city'));
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            // handle region button
            (function(btn) {
                btn.click(function() {
                    if (UserCountryMap.mode != "region") {
                        $('#UserCountryMap-view-mode-buttons a').removeClass('activeIcon');
                        UserCountryMap.mode = "region";
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        updateState(UserCountryMap.lastSelected);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    }
                });
            })($('#UserCountryMap-btn-region'));
    
    
            // add loading indicator overlay
            var bl = $('<div id="UserCountryMap-black"></div>');
            bl.hide();
            $('#UserCountryMap_map').append(bl);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
            var infobtn = $('.UserCountryMap-info-btn');
            infobtn.on('mouseenter', function(e) {
                $(infobtn.data('tooltip-target')).show();
            }).on('mouseleave', function(e) {
                $(infobtn.data('tooltip-target')).hide();
            });
            $('.UserCountryMap-tooltip').hide();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        }
    
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
    
         * updateState, called whenever the view changes
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
         */
        function updateState(id) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            // double check view mode
            if (UserCountryMap.mode == "city" && id.length != 3) {
                // city mode is reserved for country views
                UserCountryMap.mode = "region";
            }
    
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
            var metric = $('#userCountryMapSelectMetrics').val();
    
    
            // store current map state
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
            UserCountryMap.widget.dashboardWidget('setParameters', {
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
                lastMap: id, viewMode: UserCountryMap.mode, lastMetric: metric
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
            });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            $('.UserCountryMap-info-btn').hide();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            try {
                // check which map to render
                if (id.length == 3) {
                    // country map
                    renderCountryMap(id, metric);
                } else {
                    // world or continent map
                    renderWorldMap(id, metric);
                }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            } catch (e) {
                // console.error(e);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                $('.UserCountryMap-info .content').html(e);
                $('.UserCountryMap-info').show();
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
            }
    
    
            _updateUI(id, metric);
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
    
            UserCountryMap.lastSelected = id;
        }
    
        /*
         * update the widgets ui according to the currently selected view
         */
    
        function _updateUI(id, metric) {
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
            // update UI
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            if (UserCountryMap.mode == "city") {
                activateButton($('#UserCountryMap-btn-city'));
            } else {
                activateButton($('#UserCountryMap-btn-region'));
            }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            var countrySelect = $('#userCountryMapSelectCountry');
            countrySelect.val(id);
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            var zoom = $('#UserCountryMap-btn-zoom');
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            if (id == 'world') zoom.addClass('inactiveIcon');
            else zoom.removeClass('inactiveIcon');
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
            // show flag icon in select box
    
            var flag = $('#userCountryMapFlag'),
                regionBtn = $('#UserCountryMap-btn-region');
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            if (id.length == 3) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                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(UserCountryMap._.no_data);
                    $('.map-title').html('');
                    return;
                }
                
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            } else {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                flag.css({
                    'background': 'none'
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                $('#UserCountryMap-btn-city').addClass('inactiveIcon').hide();
    
                $('span', regionBtn).html(regionBtn.data('country'));
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            }
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            var mapTitle = id.length == 3 ?
                    UserCountryMap.countriesByIso[id].name :
                    $('#userCountryMapSelectCountry option[value='+id+']').html(),
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
                totalVisits = 0;
            // update map title
            $('.map-title').html(mapTitle);
            // update total visits for that region
            if (id.length == 3) {
                totalVisits = UserCountryMap.countriesByIso[id]['nb_visits'];
            } else if (id.length == 2) {
                $.each(UserCountryMap.countriesByIso, function(iso, country) {
                    if (UserCountryMap.ISO3toCONT[iso] == id) {
                        totalVisits += country['nb_visits'];
                    }
                });
            } else {
                totalVisits = UserCountryMap.config.visitsSummary['nb_visits'];
            }
    
    
            if (id.length == 3) {
                $('.map-stats').html(formatValueForTooltips(UserCountryMap.countriesByIso[id], metric, 'world'));
            } else {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                $('.map-stats').html(
                    UserCountryMap._.nb_visits.replace('%s', '<b>'+formatNumber(totalVisits) + '</b>') +(id != 'world' ? ' ('+
                formatPercentage(totalVisits / worldTotalVisits)+')' : '')
                );
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        }
    
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
        /*
         * 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;
                    }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                }, true);
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                function countryFill(data) {
    
                    var d = UserCountryMap.countriesByIso[data.iso];
                    if (d === null) {
                        return UserCountryMap.config.noDataColor;
                    } else {
    
                        return colscale.getColor(d[metric]);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                }
    
                // Apply the color scale to the map.
                map.getLayer('countries')
                .style('fill', countryFill)
                .on('mouseenter', function(d, path, evt) {
                        if (evt.shiftKey) { // highlight on mouseover with shift pressed
                            path.attr('fill', '#f4f45b');
                        }
                    })
                .on('mouseleave', function(d, path, evt) {
                        if ($.inArray(UserCountryMap.countriesByIso[d.iso].name, _rowEvolution.labels) == -1) {
                            path.attr('fill', countryFill(d)); // reset color
                        }
                    });
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
    
                // Update the map tooltips.
    
                map.getLayer('countries').tooltips(function(data) {
                    var metric = $('#userCountryMapSelectMetrics').val(),
                        country = UserCountryMap.countriesByIso[data.iso];
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    return '<h3>'+country.name + '</h3>'+
                        formatValueForTooltips(country, metric, target);
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
                });
            }
    
            // if the view hasn't changed (but probably the selected metric),
            // all we need to do is to recolor the current map.
            if (target == UserCountryMap.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
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                map.addLayer('countries', {
                    name: 'context',
                    filter: function(pd) {
                        return UserCountryMap.countriesByIso[pd.iso] === undefined;
                    },
                    tooltips: function(pd) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        return '<h3>'+pd.name+'</h3>No Visits';
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    }
                });
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
    
                // add a layer for selectable countries = for which we have data
                // available in the current report
    
                map.addLayer('countries', { name: 'countryBG', filter: function(pd) {
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
                    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();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        if (evt.shiftKey || _rowEvolution.labels.length) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            if (evt.altKey) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                path.attr('fill', '#f4f45b');
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                addMultipleRowEvolution('getCountry', UserCountryMap.countriesByIso[data.iso].name);
                            } else {
                                showRowEvolution('getCountry', UserCountryMap.countriesByIso[data.iso].name);
                                updateColorsAndTooltips(metric);
                            }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            return;
                        }
    
                        if (UserCountryMap.lastSelected != 'world' || UserCountryMap.countriesByIso[data.iso] === undefined) {
                            tgt = data.iso;
    
                            tgt = UserCountryMap.ISO3toCONT[data.iso];
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
                    }
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
    
                updateColorsAndTooltips(metric);
            });
        }
    
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * updateMap is called by renderCountryMap() and renderWorldMap()
         */
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
        function _updateMap(svgUrl, callback) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            map.loadMap(config.svgBasePath + svgUrl, function() {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
                map.clear();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                onResize();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                callback();
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                $('.ui-tooltip').remove(); // remove all existing tooltips
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            }, { padding: -3});
        }
    
    
        function indicateLoading() {
            $('#UserCountryMap-black').show();
            $('#UserCountryMap-black').css('opacity', 0);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            $('#UserCountryMap-black').animate({ opacity: 0.5 }, 400);
    
            $('#UserCountryMap .loadingPiwik').show();
        }
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
    
    
        function loadingComplete() {
            $('#UserCountryMap-black').hide();
            $('#UserCountryMap .loadingPiwik').hide();
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
        }
    
    
        /*
         * returns a quantifiable value for a given metric
         */
        function quantify(d, metric) {
            if (!metric) metric = $('#userCountryMapSelectMetrics').val();
            switch (metric) {
                case 'avg_time_on_site':
                    return d.sum_visit_length / d.nb_visits;
                case 'bounce_rate':
                    return d.bounce_count / d.nb_visits;
                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.
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function aggregate(rows, groupBy) {
    
    
            var groups = {};
            $.each(rows, function(i, row) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                var g_id = groupBy ? groupBy(row) : 'X';
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                g_id = g_id === true ? $.isNumeric(i) && i === Number(i) ? false : i : g_id;
    
                if (g_id) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    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];
                    });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            $.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 * 100 / group.bounce_count);
                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)+"%";
            });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            return groupBy ? groups : groups.X;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function displayUnlocatableCount(unlocated, total) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            $('.unlocated-stats').html(
                $('.unlocated-stats').data('tpl')
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    .replace('%s', unlocated)
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    .replace('%p', '('+formatPercentage(unlocated/total)+')')
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    .replace('%c', UserCountryMap.countriesByIso[UserCountryMap.lastSelected].name)
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            );
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            $('.UserCountryMap-info-btn').show();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        }
    
    
        /*
         * renders a country map (either region or city view)
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function renderCountryMap(iso) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            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
             */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            function updateRegionColors() {
    
                indicateLoading();
                // load data from Piwik API
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                $.ajax({
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    url: 'index.php',
                    type: 'POST',
                    data: _reportParams('UserCountry', 'getRegion', UserCountryMap.countriesByIso[iso].iso2),
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    dataType: 'json',
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    success : function(data) {
    
    
                        loadingComplete();
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        var regionDict = {},
                            totalCountryVisits = UserCountryMap.countriesByIso[iso].nb_visits,
                            unlocated = totalCountryVisits;
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
                        // UserCountryMap.lastReportMetricStats = {};
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        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) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            regionDict[data.reportMetadata[i].region] = $.extend(row, data.reportMetadata[i], {
                                curMetric: quantify(row, metric)
                            });
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
                        });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
                        var metric = $('#userCountryMapSelectMetrics').val();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        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;
                            });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            //if (!UserCountryMap.aggregate.partial) regionDict = {};
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            $.each(aggregated, function(id, group) {
                                group.curMetric = quantify(group, metric);
                                regionDict[id] = group;
                            });
                        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        $.each(regionDict, function(key, region) {
                            if (regionExistsInMap(key)) unlocated -= region.nb_visits;
                        });
                        displayUnlocatableCount(unlocated, totalCountryVisits);
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        // create color scale
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        colscale = getColorScale(regionDict, 'curMetric', null, true);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        function regionFill(data) {
    
                            var code = regionCode(data);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            return regionDict[code] === undefined ? '#fff' : colscale.getColor(regionDict[code].curMetric);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        }
    
                        // apply colors to map
                        map.getLayer('regions')
                        .style('fill', regionFill)
                        .style('stroke', function(data) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            return regionDict[regionCode(data)] === undefined ? '#bbb' : '#3C6FB6';
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        }).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) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                return '<h3>'+data.name+'</h3><p>'+UserCountryMap._.nb_visits.replace('%s', '<b>0</b>')+'</p>';
    
                            }
                            return '<h3>'+data.name+'</h3>'+
    
                                formatValueForTooltips(region, metric, iso);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        }).on('click', function(d, path, evt) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            var region = regionDict[regionCode(d)];
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            if (region && region.label) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                if (evt.shiftKey) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                    path.attr('fill', '#f4f45b');
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                    addMultipleRowEvolution('getRegion', region.label);
                                } else {
                                    map.getLayer('regions').style('fill', regionFill);
                                    showRowEvolution('getRegion', region.label);
                                }
                            }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        }).on('mouseenter', function(d, path, evt) {
                            var region = regionDict[regionCode(d)];
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            if (region && region.label) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                if (evt.shiftKey) {
                                    path.attr('fill', '#f4f45b');
                                }
                            }
                        }).on('mouseleave', function(d, path, evt) {
                            var region = regionDict[regionCode(d)];
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            if (region && region.label) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                if ($.inArray(region.label, _rowEvolution.labels) == -1) {
                                    // reset color
                                    path.attr('fill', regionFill(d));
                                }
                            }
                        }).style('cursor', function(d) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            return regionDict[regionCode(d)] && regionDict[regionCode(d)].label ? 'pointer' : 'default';
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
                        // check for regions missing in the map
                        $.each(regionDict, function(code, region) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            if (!regionExistsInMap(code)) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                console.warn('possible region mismatch!', code, region.nb_visits);
                            }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                });
            }
    
    
            /*
             * updates the city symbols in the current map
             * this happens once a new country is loaded and
             * whenever the metric changes
             */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            function updateCitySymbols() {
    
                // color regions in white as background for symbols
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                if (map.getLayer('regions')) map.getLayer('regions').style('fill', '#fff');
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
                indicateLoading();
    
                // get visits per city from API
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                $.ajax({
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    url: 'index.php',
                    data: _reportParams('UserCountry', 'getCity', UserCountryMap.countriesByIso[iso].iso2),
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    dataType: 'json',
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    type: 'POST',
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    success : function(data) {
    
    
                        loadingComplete();
    
                        var metric = $('#userCountryMapSelectMetrics').val(),
                            colscale,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            totalCountryVisits = UserCountryMap.countriesByIso[iso].nb_visits,
                            unlocated = totalCountryVisits,
    
                            cities = [];
    
                        // merge reportData and reportMetadata to cities array
    
                        $.each(data.reportData, function(i, row) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            unlocated -= row.nb_visits;
    
                            cities.push($.extend(row, data.reportMetadata[i], {
                                curMetric: quantify(row, metric)
                            }));
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        displayUnlocatableCount(unlocated, totalCountryVisits);
    
    
                        // sort by current metric
                        cities.sort(function(a, b) { return b.curMetric - a.curMetric; });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
                        colscale = getColorScale(cities, metric);
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        // construct scale
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        var radscale = $K.scale.linear(cities.concat({ curMetric: 0 }), 'curMetric');
    
    
                        var area = map.container.width() * map.container.height(),
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            sumArea = 0,
                            f = {
                                nb_visits: 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);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        radscale = $K.scale.sqrt(cities.concat({ curMetric: 0 }), 'curMetric').range([2, maxRad+2]);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        var is_rate = metric.substr(0,3) != 'nb_' || metric == 'nb_actions_per_visit';
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        var citySymbols = map.addSymbols({
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            type: $K.LabeledBubble,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            clustering: 'noverlap',
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            clusteringOpts: {
                                size: 128,
                                tolerance: 0
                            },
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            title: function(d) {
                                return radscale(d.curMetric) > 10 ? formatNumber(d.curMetric) : '';
                            },
                            labelattrs: {
                                fill: '#fff',
                                'font-size': 11,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                stroke: false,
                                cursor: 'pointer'
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            },
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            filter: function(d) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                if (isNaN(d.lat) || isNaN(d.long)) return false;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                return is_rate ? d.nb_visits > 5 && d.curMetric : d.curMetric;
                            },
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            aggregate: function(rows) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                var row = aggregate(rows);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                row.city_names = [];
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                row.label = rows[0].label; // keep label of biggest city for row evolution
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                $.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 ? ' '+UserCountryMap._.and_n_others.replace('%s', (row.city_names.length-1)) : '');
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                row.curMetric = quantify(row, metric);
                                return row;
                            },
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            sortBy: 'radius desc',
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            location: function(city) { return [city.long, city.lat]; },
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            radius: function(city) { return radscale(city.curMetric); },
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            tooltip: function(city) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                return '<h3>'+city.city_name+'</h3>'+
                                    formatValueForTooltips(city, metric, iso);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            attrs: function(city) {
                                return {
                                    fill: colscale.getColor(city.curMetric),
                                    'fill-opacity': 0.7,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                    stroke: '#fff',
                                    cursor: 'pointer'
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                };
                            },
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            mouseenter: function(city, symbol, evt) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                symbol.path.attr({
                                    'fill-opacity': 1,
                                    'stroke': '#000000',
                                    'stroke-opacity': 1,
                                    'stroke-width': 2
                                });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                if (evt.shiftKey) {
                                    symbol.path.attr({ fill: '#f4f45b' });
                                    if (symbol.label) symbol.label.attr({ fill: '#000' });
                                }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            },
                            mouseleave: function(city, symbol) {
                                symbol.path.attr({
                                    'fill-opacity': 0.7,
                                    'stroke-opacity': 1,
                                    'stroke-width': 1,
                                    'stroke': '#ffffff'
                                });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                                if ($.inArray(city.label, _rowEvolution.labels) == -1) {
                                    symbol.path.attr({ fill: colscale.getColor(city.curMetric) });
                                    if (symbol.label) symbol.label.attr({ fill: '#fff' });
                                }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            },
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                            click: function(city, symbol, evt) {
                                if (evt.shiftKey) {
                                    addMultipleRowEvolution('getCity', city.label);
                                    symbol.path.attr('fill', '#f4f45b');
                                    if (symbol.label) symbol.label.attr('fill', '#000');
                                } else {
                                    showRowEvolution('getCity', city.label);
                                    citySymbols.evaluate({
                                        attrs: function(city) {
                                            return { fill: colscale.getColor(city.curMetric) };
                                        }
                                    });
                                }
                            }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    }
                });
            }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    ..  
    Gregor Aisch a validé
            _updateMap(iso + '.svg', function() {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                // 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();
    
                        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 '<h3>'+country.name+'</h3>'+
    
                            formatValueForTooltips(country, metric, 'world');
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                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: UserCountryMap.mode != "region" ? "regions2" : "regions",
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    styles: {
                        stroke: '#aaa'
                    },
    
                    click: function(d, p, evt) {
                        evt.stopPropagation();
                    }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                function filtCountryLabels(data) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    return data.iso != iso && Math.abs(map.getLayer('context-clickable').getPath(data.iso).path.area()) > 700;
                }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                // 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;
                }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                map.addSymbols({
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    data: map.getLayer('context-clickable').getPathsData(),
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    type: $K.Label,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    filter: filtCountryLabels,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    location: countryLabelPos,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    text: function(data) { return UserCountryMap.countriesByIso[data.iso].iso2; },
                    'class': 'countryLabelBg'
                });
                map.addSymbols({
                    data: map.getLayer('context-clickable').getPathsData(),
                    type: $K.Label,
                    filter: filtCountryLabels,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    location: countryLabelPos,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    text: function(data) { return UserCountryMap.countriesByIso[data.iso].iso2; },
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    'class': 'countryLabel'
                });
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                if (!UserCountryMap.countriesByIso[iso]) return;
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                if (UserCountryMap.mode == "region") {
                    updateRegionColors();
                } else {
                    updateCitySymbols();
                }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            });
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        var _rowEvolution = { labels: [], method: false };
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
        function addMultipleRowEvolution(method, label) {
            if (method != _rowEvolution.method) {
                _rowEvolution = { method: method, labels: [] };
            }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            _rowEvolution.labels.push(label);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
         * opens row evolution popover
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
         */
        function showRowEvolution(method, label) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            var box = Piwik_Popover.showLoading('Row Evolution'),
                multiple;
    
            multiple = method == _rowEvolution.method && _rowEvolution.labels.length > 0;
    
            if (multiple) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                _rowEvolution.labels.push(label);
                $.each(_rowEvolution.labels, function(i,l) {
                    _rowEvolution.labels[i] = l.replace(/, /g, '%2C%20');
                });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
            var requestParams = $.extend(UserCountryMap.reqParams, {
                apiMethod: 'UserCountry.' + method,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                label: multiple ? _rowEvolution.labels.join(',') : label.replace(/, /g, '%2C%20'),
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                disableLink: 1,
                module: 'CoreHome',
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                action: multiple ? 'getMultiRowEvolutionPopover' : 'getRowEvolutionPopover'
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            });
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            $.ajax({
                url: 'index.php',
                type: 'POST',
                dataType: 'html',