191 lines
5.3 KiB
JavaScript
191 lines
5.3 KiB
JavaScript
/**
|
|
* 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 <a href="./jvm-map/">jvm.Map</a> for more information.
|
|
* @param {Function} params.mapNameByCode Function to generate map name by region code. Default value is:
|
|
<pre>
|
|
function(code, multiMap) {
|
|
return code.toLowerCase()+'_'+
|
|
multiMap.defaultProjection+'_en';
|
|
}
|
|
</pre>
|
|
* @param {Function} params.mapUrlByCode Function to generate map url by region code. Default value is:
|
|
<pre>
|
|
function(code, multiMap){
|
|
return 'jquery-jvectormap-data-'+
|
|
code.toLowerCase()+'-'+
|
|
multiMap.defaultProjection+'-en.js';
|
|
}
|
|
</pre>
|
|
*/
|
|
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
|
|
.$("<div/>")
|
|
.addClass("jvectormap-goback")
|
|
.text("Back")
|
|
.appendTo(this.params.container);
|
|
this.backButton.hide();
|
|
this.backButton.click(function () {
|
|
that.goBack();
|
|
});
|
|
|
|
this.spinner = jvm
|
|
.$("<div/>")
|
|
.addClass("jvectormap-spinner")
|
|
.appendTo(this.params.container);
|
|
this.spinner.hide();
|
|
};
|
|
|
|
jvm.MultiMap.prototype = {
|
|
addMap: function (name, config) {
|
|
var cnt = jvm.$("<div/>").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"
|
|
);
|
|
},
|
|
};
|