Spaces:
No application file
No application file
| class MauticMap { | |
| static TYPES = { | |
| 'markers': 0, | |
| 'regions': 1, | |
| }; | |
| static SETTINGS = { | |
| backgroundColor: 'transparent', | |
| zoomOnScroll: false, | |
| zoomAnimate: true, | |
| markerStyle: { | |
| initial: { | |
| fill: '#40C7B5' | |
| }, | |
| selected: { | |
| fill: '#40C7B5' | |
| } | |
| }, | |
| regionStyle: { | |
| initial: { | |
| "fill": '#dce0e5', | |
| "fill-opacity": 1, | |
| "stroke": 'none', | |
| "stroke-width": 0, | |
| "stroke-opacity": 1 | |
| }, | |
| hover: { | |
| "fill-opacity": 0.7, | |
| "cursor": 'pointer' | |
| } | |
| }, | |
| map: 'world_mill_en', | |
| series: { | |
| regions: [{ | |
| scale: ['#b9ebe4', '#40C7B5'], | |
| normalizeFunction: 'polynomial', | |
| }] | |
| }, | |
| onRegionOver: () => { | |
| document.body.style.cursor = 'pointer'; | |
| }, | |
| onRegionOut: () => | |
| { | |
| document.body.style.cursor = 'default'; | |
| } | |
| } | |
| constructor(wrapper, typeKey = 'regions' ) { | |
| this.type = MauticMap.TYPES[typeKey]; | |
| this.scope = mQuery(wrapper); | |
| this.mapData = this.getMapData(); | |
| this.settings = MauticMap.SETTINGS; | |
| this.map = this.getMapsInScope(); | |
| this.legendEnabled = this.isLegendEnabled(); | |
| this.statUnit = this.getStatUnitFromItem(this.map); | |
| this.settings.onRegionTipShow = (event, label, index) => { | |
| if (this.mapData) { | |
| const value = this.mapData[index]; | |
| if (value > 0) { | |
| const tooltip = `<b>${label.html()}</b></br>${value} ${this.statUnit}${(value > 1) ? 's' : ''}`; | |
| label.html(tooltip); | |
| } | |
| } | |
| } | |
| if (this.legendEnabled) { | |
| this.settings.series.regions[0].legend = { | |
| horizontal: true, | |
| title: '<div data-map-legend="true"></div>', | |
| } | |
| } | |
| this.mapOptions = this.scope.find('[data-map-option]'); | |
| } | |
| init() { | |
| this.initSeries(this.mapData); | |
| this.initMap(); | |
| } | |
| initSeries(data) { | |
| if (this.type === MauticMap.TYPES['regions']) { | |
| this.settings.series.regions[0].values = data; | |
| this.settings.markers = {}; | |
| } | |
| if(this.type === MauticMap.TYPES['markers']) { | |
| this.settings.series.regions[0].values = {}; | |
| this.settings.markers = data; | |
| } | |
| } | |
| isLegendEnabled() { | |
| return this.map.data('legend-enabled'); | |
| } | |
| getMapsInScope() { | |
| return this.scope.find('.vector-map'); | |
| } | |
| getStatUnitFromItem(item) { | |
| return mQuery(item).data('stat-unit'); | |
| } | |
| setStatUnit(value) { | |
| this.statUnit = value; | |
| } | |
| getMapData() { | |
| const map = this.getMapsInScope(); | |
| let data = map.data('map-data'); | |
| if (typeof data === 'undefined' || !data.length) { | |
| try { | |
| data = JSON.parse(map.text()); | |
| map.data('map-data', data) | |
| map.attr('data-map-data', JSON.stringify(data)); | |
| } catch (error) { | |
| return {}; | |
| } | |
| } | |
| return data; | |
| } | |
| renderMap() { | |
| // Map render causes a JS error on FF when the element is hidden | |
| if (this.scope.is(':visible')) { | |
| this.map.text(''); | |
| this.map.vectorMap(this.settings); | |
| mQuery(this.map).addClass('map-rendered'); | |
| } | |
| }; | |
| /** | |
| * Destroy a jVector map | |
| */ | |
| destroyMap() { | |
| if (this.map.length) { | |
| const mapObj = this.map.vectorMap('get', 'mapObject'); | |
| if (mapObj) { | |
| mapObj.removeAllMarkers(); | |
| mapObj.remove(); | |
| this.map.empty(); | |
| this.map.removeClass('map-rendered'); | |
| } | |
| } | |
| }; | |
| /** | |
| * Get legend content from option | |
| */ | |
| getOptionLegendText(option) { | |
| return option.data('legend-text'); | |
| } | |
| /** | |
| * Add click listeners to map option buttons | |
| */ | |
| addMapOptionsListener() { | |
| if (this.mapOptions.length) { | |
| mQuery(this.mapOptions).on('click', (event) => { | |
| const currentOption = mQuery(event.currentTarget); | |
| const newValues = currentOption.data('map-series'); | |
| const legendText = this.getOptionLegendText(currentOption); | |
| const statUnit = this.getStatUnitFromItem(currentOption); | |
| this.setMapValues(newValues); | |
| this.setActiveOption(currentOption); | |
| if (this.legendEnabled) { | |
| this.setLegend(legendText); | |
| } | |
| if (statUnit) { | |
| this.setStatUnit(statUnit); | |
| } | |
| }); | |
| if (this.legendEnabled) { | |
| const defaultOption = mQuery(this.mapOptions[0]); | |
| const legendText = this.getOptionLegendText(defaultOption); | |
| this.setLegend(legendText); | |
| } | |
| } | |
| } | |
| setActiveOption(option) { | |
| this.mapOptions.removeClass('active'); | |
| option.addClass('active'); | |
| } | |
| setLegend(legendText) { | |
| const mapLegend = this.scope.find('[data-map-legend]'); | |
| mQuery(mapLegend).text(legendText); | |
| } | |
| setMapValues(values) { | |
| const mapObject = this.map.vectorMap('get', 'mapObject'); | |
| const dataSeries = mapObject.series.regions[0]; | |
| this.mapData = values; | |
| mapObject.reset(); | |
| if (this.type === MauticMap.TYPES['regions'] && dataSeries) { | |
| // Force map color scaling | |
| this.unsetExtremeValues(dataSeries); | |
| dataSeries.setValues(values); | |
| } else if (this.type === MauticMap.TYPES['markers']) { | |
| this.settings.markers[0].setValues(values) | |
| } | |
| } | |
| unsetExtremeValues(dataSeries) { | |
| dataSeries.params.min = undefined; | |
| dataSeries.params.max = undefined; | |
| } | |
| initMap() { | |
| if (this.scope.length) { | |
| // Check if map is not already rendered | |
| if (this.scope.children('.map-rendered').length) { | |
| return; | |
| } | |
| const map = this.getMapsInScope() | |
| this.renderMap(map); | |
| this.addMapOptionsListener(); | |
| } | |
| } | |
| } | |
| Mautic.initMap = (wrapper, typeKey) => { | |
| const map = new MauticMap(wrapper, typeKey); | |
| map.init(); | |
| if (!Mautic.mapObjects) Mautic.mapObjects = []; | |
| Mautic.mapObjects.push(map); | |
| return map; | |
| } |