Alex Alex - 7 months ago 34
Javascript Question

Select only one area on SVG map using jQuery

I am using Mapael, a Raphael extension in order to deliver an interactive map, so far I have coded it so you can select multiple areas and make a div element visible according to the area clicked, and now I would like to be able to restrict the user to only selecting one area at a time.

http://plnkr.co/edit/2UAl4Yax99dJAPIDWuTy?p=preview

here is the part of the code that covers the click function.

eventHandlers: {
click: function(e, id, mapElem) {
var newData = {
'areas': {}
};
if (mapElem.originalAttrs.fill == "#f4f4e8" && "id[^='department']") {
newData.areas[id] = {
attrs: {
fill: "#0088db"
}
};
$('#' + id).css("visibility", "visible")
}
else if (mapElem.originalAttrs.fill == "#0088db" && "id[^='department']") {
newData.areas[id] = {
attrs: {
fill: "#f4f4e8"
}
};
$("#" + id).css("visibility", "hidden")
}
$(".mapcontainer").trigger('update', [newData]);
}
},


Again, the map shown here allows you to click multiple areas, however I would like to make it so you can just select one area at a time.

I've tried for quite a while coming up with a solution myself, however I think I've had coders block somewhat and could do with a little advice to point me in the right direction. I've been experimenting with .bind, .target and also with the mapael afterUpdate capabilites (shown below if it can help).

var options = {
mapOptions: {}, // was updatedOptions
replaceOptions: false // replace opt.resetPlots/resetAreas: whether mapsOptions should entirely replace current map options, or just extend it,
newPlots: {}, // was newPlots
newLinks: {}, // was opt.newLinks
deletePlotKeys: [], // was deletedPlots
deleteLinkKeys: [], // was opt.deletedLinks
setLegendElemsState: true, // is new
animDuration: 0, // was opt.animDuration
afterUpdate: function(){} // was opt.afterUpdate
};
$(".container").trigger('update', [options]);


I'm not sure if the solution could be something like looping through the SVG paths when first clicked to ensure that no element has been clicked/has the blue fill, and then going from there? Although this sounds a bit overly complicated to me and I'm not sure how it would be implemented in practice.

Answer

I have found a solution to this problem, here is a plnkr of it;

eventHandlers: {
                    click: function (e, id, mapElem, textElem) {
                        var newData = {
                            'areas': {}
                        };

                        if (previousSelectedElementId !== null) {
                            newData.areas[previousSelectedElementId] = {
                                attrs: {
                                    fill: "#5ba4ff"
                                }
                            };
                        }

                        if (mapElem.originalAttrs.fill == "#5ba4ff") {
                            newData.areas[id] = {
                                attrs: {
                                    fill: "#0088db"
                                }
                            };
                            previousSelectedElementId = id;
                        } else {
                            newData.areas[id] = {
                                attrs: {
                                    fill: "#5ba4ff"
                                }
                            };
                            previousSelectedElementId = null;
                        }
                        $(".mapcontainer").trigger('update', [newData]);
                    }

http://jsfiddle.net/neveldo/wfftgu20/