/** * Creates map with drill-down functionality. * @constructor * @param {Object} params Parameters to initialize map with. * @param {Number} params.maxLevel Maximum number of levels user can go through * @param {Object} params.main Config of the main map. See jvm.Map for more information. * @param {Function} params.mapNameByCode Function to generate map name by region code. Default value is:
function(code, multiMap) {
  return code.toLowerCase()+'_'+
         multiMap.defaultProjection+'_en';
}
* @param {Function} params.mapUrlByCode Function to generate map url by region code. Default value is:
function(code, multiMap){
  return 'jquery-jvectormap-data-'+
         code.toLowerCase()+'-'+
         multiMap.defaultProjection+'-en.js';
}
*/ jvm.MultiMap = function (params) { var that = this; this.maps = {}; this.params = jvm.$.extend(true, {}, jvm.MultiMap.defaultParams, params); this.params.maxLevel = this.params.maxLevel || Number.MAX_VALUE; this.params.main = this.params.main || {}; this.params.main.multiMapLevel = 0; this.history = [this.addMap(this.params.main.map, this.params.main)]; this.defaultProjection = this.history[0].mapData.projection.type; this.mapsLoaded = {}; this.mapsLoadedData = {}; this.params.container.css({ position: "relative" }); this.backButton = jvm .$("
") .addClass("jvectormap-goback") .text("Back") .appendTo(this.params.container); this.backButton.hide(); this.backButton.click(function () { that.goBack(); }); this.spinner = jvm .$("
") .addClass("jvectormap-spinner") .appendTo(this.params.container); this.spinner.hide(); }; jvm.MultiMap.prototype = { addMap: function (name, config) { var cnt = jvm.$("
").css({ width: "100%", height: "100%", }); this.params.container.append(cnt); this.maps[name] = new jvm.Map(jvm.$.extend(config, { container: cnt })); if (this.params.maxLevel > config.multiMapLevel) { this.maps[name].container.on( "regionClick.jvectormap", { scope: this }, function (e, code) { var multimap = e.data.scope, mapName = multimap.params.mapNameByCode(code, multimap); if ( !multimap.drillDownPromise || multimap.drillDownPromise.state() !== "pending" ) { multimap.drillDown(mapName, code); } }, ); } return this.maps[name]; }, downloadMap: function (code) { var that = this, deferred = jvm.$.Deferred(); const { getDrillDownMap } = this.params; const handleMapData = function (data) { that.mapsLoaded[code] = true; that.mapsLoadedData[code] = data; deferred.resolve(); }; if (!this.mapsLoaded[code]) { if (getDrillDownMap && typeof getDrillDownMap === "function") { const result = getDrillDownMap(code); if (result && typeof result.then === "function") { result .then((data) => { handleMapData(data); }) .catch(() => { deferred.reject(); }); } else { handleMapData(result); } return deferred; } jvm.$.get(this.params.mapUrlByCode(code, this)).then( function (data) { handleMapData(data); }, function () { deferred.reject(); }, ); } else { deferred.resolve(); } return deferred; }, drillDown: function (name, code) { var currentMap = this.history[this.history.length - 1], that = this, focusPromise = currentMap.setFocus({ region: code, animate: true }), downloadPromise = this.downloadMap(code); focusPromise.then(function () { if (downloadPromise.state() === "pending") { that.spinner.show(); } }); downloadPromise.always(function () { that.spinner.hide(); }); this.drillDownPromise = jvm.$.when(downloadPromise, focusPromise); this.drillDownPromise.then(function () { const { content } = that.mapsLoadedData[code]; currentMap.params.container.hide(); if (!that.maps[name]) { jvm.$.fn.vectorMap("addMap", name, content); that.addMap(name, { map: name, multiMapLevel: currentMap.params.multiMapLevel + 1, }); } else { that.maps[name].params.container.show(); } that.history.push(that.maps[name]); that.backButton.show(); }); }, goBack: function () { var currentMap = this.history.pop(), prevMap = this.history[this.history.length - 1], that = this; currentMap .setFocus({ scale: 1, x: 0.5, y: 0.5, animate: true }) .then(function () { currentMap.params.container.hide(); prevMap.params.container.show(); prevMap.updateSize(); if (that.history.length === 1) { that.backButton.hide(); } prevMap.setFocus({ scale: 1, x: 0.5, y: 0.5, animate: true }); }); }, }; jvm.MultiMap.defaultParams = { mapNameByCode: function (code, multiMap) { return code.toLowerCase() + "_" + multiMap.defaultProjection + "_en"; }, mapUrlByCode: function (code, multiMap) { return ( "jquery-jvectormap-data-" + code.toLowerCase() + "-" + multiMap.defaultProjection + "-en.js" ); }, };