Skip to content
Extraits de code Groupes Projets
realtime-map.js 14,1 ko
Newer Older
  • Learn to ignore specific revisions
  • // # RealTimeMap
    
    window.RealTimeMap = {};
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    /*
     * main function, called from realtime-map.tpl
     */
    
    RealTimeMap.run = function(config) {
    
        var map = $K.map('#RealTimeMap_map'),
            main = $('#RealTimeMap_container'),
            worldTotalVisits = 0,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            maxVisits = 100,
    
            width = main.width(),
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            scale = width * (width*0.7) / 180000,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            lastTimestamp = -1,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            lastVisits = [],
            visitSymbols,
            oldest,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            isFullscreenWidget = $('.widget').parent().get(0) == document.body,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            now,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            nextReqTimer,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            symbolFadeInTimer = [],
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            colorMode = 'default',
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            currentMap = 'world',
    
            currentTheme = 'white',
            colorTheme = {
                white: {
                    bg: '#fff',
                    fill: '#aa9'
                },
                black: {
                    bg: '#000',
                    fill: '#444440'
                }
            };
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        RealTimeMap.widget = $('#widgetRealTimeMaprealtimeMap').parent();
    
    
        window._liveMap = map;
        RealTimeMap.config = config;
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        var preset = RealTimeMap.widget.dashboardWidget('getWidgetObject').parameters;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        if (preset) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            currentTheme = preset.colorTheme;
            colorMode = preset.colorMode;
            currentMap = preset.lastMap;
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * returns the parameters for API calls, extended from
         * RealTimeMap.reqParams which is set in template
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function _reportParams(firstRun) {
    
            var params = $.extend(RealTimeMap.reqParams, {
                module: 'API',
                method: 'Live.getLastVisitsDetails',
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                filter_limit: maxVisits,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                showColumns: ['latitude','longitude','actions','lastActionTimestamp',
                    'visitLocalTime','city','country','referrerType','referrerName',
                    'referrerTypeName','browserIcon','operatingSystemIcon',
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    'countryFlag','idVisit','actionDetails'].join(','),
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                minTimestamp: firstRun ? -1 : lastTimestamp,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                date: 'today'
    
            });
            return params;
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * wrapper around jQuery.ajax, moves token_auth parameter
         * to POST data while keeping other parameters as GET
         */
        function ajax(params) {
            var token_auth = params.token_auth;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            delete params['token_auth'];
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            return $.ajax({
                url: 'index.php?' + $.param(params),
                dataType: 'json',
                data: { token_auth: token_auth },
                type: 'POST'
            });
        }
    
    
        /*
         * updateMap is called by renderCountryMap() and renderWorldMap()
         */
        function _updateMap(svgUrl, callback) {
            map.loadMap(config.svgBasePath + svgUrl, function() {
                map.clear();
                onResize();
                callback();
                $('.ui-tooltip').remove(); // remove all existing tooltips
            }, { padding: -3});
        }
    
        /*
         * resizes the map to widget dimensions
         */
        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é
        /*
         * 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(RealTimeMap._resizeTimer);
            RealTimeMap._resizeTimer = setTimeout(onResize, 300);
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * returns value between 0..1, where 1 means that the
         * visit is fresh, and 0 means the visit is almost gone
         * from the map
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function age(r) {
            var o = (r.lastActionTimestamp - oldest) / (now - oldest);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            return Math.min(1, Math.max(0, o));
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * returns the content of the tooltip displayed for each
         * visitor on the map
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function visitTooltip(r) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            var ds = now - r.lastActionTimestamp,
                ad = r.actionDetails,
                ico = function(src) { return '<img src="'+src+'" alt="" class="icon" />&nbsp;'; },
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                val = function(val) { return '<b>'+Math.round(val)+'</b>'; };
            return '<h3>'+r.city+' / '+r.country+'</h3>'+
                // icons
                ico(r.countryFlag)+ico(r.browserIcon)+ico(r.operatingSystemIcon)+'<br/>'+
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                // last action
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                (ad && ad.length && ad[ad.length-1].pageTitle ? '<em>' + ad[ad.length-1].pageTitle+'</em><br/>' : '')+
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                // time of visit
                (ds < 90 ? RealTimeMap._.seconds_ago.replace('%s', '<b>'+val(ds)+'</b>')
                : ds < 5400 ? RealTimeMap._.minutes_ago.replace('%s', '<b>'+val(ds/60)+'</b>')
                : ds < 129600 ? RealTimeMap._.hours_ago.replace('%s', '<b>'+val(ds/3600)+'</b>')
                : RealTimeMap._.days_ago.replace('%s', '<b>'+val(ds/86400)+'</b>'))+'<br/>'+
                // either from or direct
                (r.referrerType == "direct" ? r.referrerTypeName :
                RealTimeMap._.from + ': '+r.referrerName) + '<br />' +
                // local time
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                '<small>'+RealTimeMap._.local_time+': '+r.visitLocalTime+'</small>';
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * the radius of the symbol depends on the lastActionTimestamp
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function visitRadius(r) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            return 3 * scale * Math.pow(age(r),4) + 2.5 * scale;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * defines the color of the map symbols.
         * depends on colorMode, which is set to 'default'
         * unless you type Shift+Alt+C
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function visitColor(r) {
            var col;
            if (colorMode == 'referrerType') {
                col = ({
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    website: '#F29007',
                    direct: '#5170AE',
                    search: '#CC3399'
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                })[r.referrerType];
            }
            // defu
            else col = chroma.hsl(42 * age(r), Math.sqrt(age(r)), 0.50 - (1-age(r))*0.45);
            return col;
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * attributes of the map symbols
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function visitSymbolAttrs(r) {
            return {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                fill: visitColor(r),
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                'fill-opacity': Math.pow(age(r),2),
                'stroke-opacity': Math.pow(age(r),1.7),
                stroke: '#fff',
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                'stroke-width': age(r),
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                r: visitRadius(r)
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            };
        }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * eventually highlights the row in LiveVisitors widget
         * that corresponds to a visit on the map
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function highlightVisit(r) {
            $('#visitsLive li#'+r.idVisit + ' .datetime')
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                .css('background', '#E4CD74');
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * removes the highlight after the mouse left
         * the visit marker on the map
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function unhighlightVisit(r) {
            $('#visitsLive li#'+r.idVisit + ' .datetime')
                .css({ background: '#E4E2D7' });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * create a nice popping animation for appearing
         * visit symbols.
         */
        function animateSymbol(s) {
            // create a white outline and explode it
            var c = map.paper.circle().attr(s.path.attrs);
            c.insertBefore(s.path);
            c.attr({ fill: false });
            c.animate({ r: c.attrs.r*3, 'stroke-width': 5 * scale, opacity: 0 }, 2500,
                'linear', function() { c.remove(); });
            // ..and pop the bubble itself
            var col = s.path.attrs.fill,
                rad = s.path.attrs.r;
            s.path.show();
            s.path.attr({ fill: '#fdb', r: 0.1, opacity: 1 });
            s.path.animate({ fill: col, r: rad }, 700, 'bounce');
    
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * this function requests new data from Live.getLastVisitsDetails
         * and updates the symbols on the map. Then, it sets a timeout
         * to call itself after the refresh time set by Piwik
         *
         * If firstRun is true, the SymbolGroup is initialized
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function refreshVisits(firstRun) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            function gotNewReport(report) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                // successful request, so set timeout for next API call
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                nextReqTimer = setTimeout(refreshVisits, config.liveRefreshAfterMs);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                now = new Date().getTime() / 1000;
    
                if (firstRun) {
                    // init symbol group
                    visitSymbols = map.addSymbols({
                        data: [],
                        type: Kartograph.Bubble,
                        sortBy: function(r) { return r.lastActionTimestamp; },
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        radius: visitRadius,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        location: function(r) { return [r.longitude, r.latitude]; },
                        attrs: visitSymbolAttrs,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        tooltip: visitTooltip,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        mouseenter: highlightVisit,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        mouseleave: unhighlightVisit,
                        click: function(r, s, evt) {
                            evt.stopPropagation();
                        }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
                    // clear existing report
                    lastVisits = [];
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                }
    
                if (report.length) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    // filter results without location
                    report = report.filter(function(r) {
                        return r.latitude !== null;
                    });
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    lastVisits = [].concat(report).concat(lastVisits).slice(0, maxVisits);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    oldest = lastVisits[lastVisits.length-1].lastActionTimestamp;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    // remove symbols that are too old
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    //console.log('before', $('circle').length, visitSymbols.symbols.length);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    var _removed = 0;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    visitSymbols.remove(function(r) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        if (r.lastActionTimestamp < oldest) _removed++;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        return r.lastActionTimestamp < oldest;
                    });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    //console.log('removed',_removed, 'now', $('circle').length);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    // update symbols that remain
                    visitSymbols.update({
                        attrs: visitSymbolAttrs
                    });
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    //console.log('updated', $('circle').length);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    // add new symbols
                    var newSymbols = [];
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    $.each(report, function(i, r) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        if (r.latitude !== null) newSymbols.push(visitSymbols.add(r));
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    });
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    //console.log('added', newSymbols.length, visitSymbols.symbols.length, $('circle').length);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    lastTimestamp = report[0].lastActionTimestamp;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    visitSymbols.layout().render();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    //console.log('rendered', visitSymbols.symbols.length, $('circle').length);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    $.each(newSymbols, function(i, s) {
                        if (i>10) return false;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        s.path.hide(); // hide new symbol at first
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        var t = setTimeout(function() { animateSymbol(s); },
                            1000 * (s.data.lastActionTimestamp - now) + config.liveRefreshAfterMs);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        symbolFadeInTimer.push(t);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            }
    
            if (firstRun && lastVisits.length) {
                // zoom changed, use cached report data
                gotNewReport(lastVisits.slice());
            } else {
                // request API for new data
                ajax(_reportParams(firstRun)).done(gotNewReport);
            }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * Set up the base map after loading of the SVG. Adds a single layer
         * that shows countries in gray with white outlines. Also this is where
         * the zoom behaviour is initialized.
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function initMap() {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            $('#widgetRealTimeMapliveMap .loadingPiwik, #RealTimeMap .loadingPiwik').hide();
            map.addLayer('countries', {
                styles: {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    fill: colorTheme[currentTheme].fill,
                    stroke: colorTheme[currentTheme].bg,
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    'stroke-width': 0.2
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                },
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                click: function(d, p, evt) {
                    evt.stopPropagation();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    if (currentMap != 'world') {  // zoom out if zoomed in
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        updateMap('world');
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    } else {  // or zoom to continent view otherwise
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                        updateMap(UserCountryMap.ISO3toCONT[d.iso]);
                    }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                },
                title: function(d) {
                    // return the country name for educational purpose
                    return d.name;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                }
            });
    
            var lastVisitId = -1,
                lastReport = [];
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            refreshVisits(true);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function storeSettings() {
            RealTimeMap.widget.dashboardWidget('setParameters', {
                lastMap: currentMap, theme: colorTheme, colorMode: colorMode
            });
        }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        /*
         * updates the map view (after changing the zoom)
         * clears all existing timeouts
         */
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        function updateMap(_map) {
            clearTimeout(nextReqTimer);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            $.each(symbolFadeInTimer, function(i, t) {
                clearTimeout(t);
            });
            symbolFadeInTimer = [];
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            try {
                map.removeSymbols();
            } catch (e) {}
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            currentMap = _map;
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            _updateMap(currentMap + '.svg', initMap);
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            storeSettings();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        }
    
        updateMap('world'); // TODO: restore last state
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        // clicking on map background zooms out
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        $('#RealTimeMap_map').click(function() {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            if (currentMap != 'world') updateMap('world');
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        });
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        // secret gimmick shortcuts
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        $(window).keydown(function(evt) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            // shift+alt+C changes color mode
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            if (evt.shiftKey && evt.altKey && evt.keyCode == 67) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                colorMode = ({
                    'default': 'referrerType',
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    referrerType: 'default'
                })[colorMode];
                storeSettings();
            }
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            function switchTheme() {
                $('#RealTimeMap').css({ background: colorTheme[currentTheme].bg });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                if (isFullscreenWidget) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    $('body').css({ background: colorTheme[currentTheme].bg });
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    $('.widget').css({ 'border-width': 1 });
                }
                map.getLayer('countries')
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                    .style('fill', colorTheme[currentTheme].fill )
                    .style('stroke', colorTheme[currentTheme].bg );
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
    
                storeSettings();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            }
    
            // shift+alt+B: switch to black background
            if (evt.shiftKey && evt.altKey && evt.keyCode == 66) {
                currentTheme = 'black';
                switchTheme();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            }
    
            // shift+alt+W: return to white background
            if (evt.shiftKey && evt.altKey && evt.keyCode == 87) {
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
                currentTheme = 'white';
                switchTheme();
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
            }
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        });
    
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        // make sure the map adapts to the widget size
    
    Gregor Aisch's avatar
    Gregor Aisch a validé
        $(window).resize(onResizeLazy);