Search code examples
javascriptmousehoverjqvmap

JS JQVMap hovercolor regions


I'm new to JS and have no idea how to get this to work. I'm trying to color multiple regions if one of them is hovered by the mouse. I'm using a switch case to get all the regions together. And this seems to work so far, because I'm getting out my test line. I'm sure I'm just missing on a tiny thing here. I appreciate any help!

jQuery(document).ready(function () {
    var red = '#E20079', blue = '#009EE0', yel = '#FFFA00';
    jQuery('#vmap').vectorMap({
        map: 'usa_en',
        backgroundColor: '#383838',
        enableZoom: false,
        showTooltip: true,
        selectedColor: null,
        onRegionOver: function(event, code, region){             
            switch(code) {
                case 'wa': case 'or': case 'ca': case 'nv': case 'id':
                case 'mt': case 'wy': case 'ut': case 'az': case 'nm':
                case 'co': case 'ne': case 'ks': case 'sd': case 'nd':
                case 'mn': case 'wi': case 'ia': case 'il': case 'ak':
                case 'hi':
                    //this output is working fine
                    document.getElementById("demo").innerHTML = code;
                    //but it won't change the color!!
                    hoverColor: 'blue';
                    break;
                case 'mo': case 'ok': case 'tx': case 'ar': case 'la':
                case 'ms': case 'al': case 'ga': case 'fl': case 'tn':
                case 'ky': case 'sc': case 'in': case 'sc':
                    hoverColor: 'yel';
                    break;
                case 'mi': case 'oh': case 'nc': case 'va': case 'wv': 
                case 'pa': case 'de': case 'nj': case 'ny': case 'ct':
                case 'ri': case 'ma': case 'vt': case 'nh': case 'me':
                case 'md': case 'dc':
                    hoverColor: 'red';
                    break;
            }
        },
        onRegionClick: function(code){
            switch(code) {
                case 'wa': case 'or': case 'ca': case 'nv': case 'id':
                case 'mt': case 'wy': case 'ut': case 'az': case 'nm':
                case 'co': case 'ne': case 'ks': case 'sd': case 'nd':
                case 'mn': case 'wi': case 'ia': case 'il': case 'ak':
                case 'hi':
                    window.open("http://www.google.com");
                    break;
                case 'mo': case 'ok': case 'tx': case 'ar': case 'la':
                case 'ms': case 'al': case 'ga': case 'fl': case 'tn':
                case 'ky': case 'sc': case 'in': case 'sc':
                    window.open("http://www.yahoo.com");
                    break;
                case 'mi': case 'oh': case 'nc': case 'va': case 'wv': 
                case 'pa': case 'de': case 'nj': case 'ny': case 'ct':
                case 'ri': case 'ma': case 'vt': case 'nh': case 'me':
                case 'md': case 'dc':
                    window.open("http://www.example.com");
                    break;                  
            }
        }
    });
});

Solution

  • I refactored a bit your code to be less redundant, in some way.

    My proposal is as follows:

    jQuery(document).ready(function () {
      // Group the codes of each state in the desired macro-areas
      var areas = [['wa','or','ca','nv','id','mt','wy','ut','az','nm','co','ne','ks','sd','nd','mn','wi','ia','il','ak','hi'],
                   ['mo','ok','tx','ar','la','ms','al','ga','fl','tn','ky','sc','in'],
                   ['mi','oh','nc','va','wv','pa','de','nj','ny','ct','ri','ma','vt','nh','me','md','dc']],
          // Assign links to areas
          links = {0: "http://www.google.com", 1: "http://www.yahoo.com", 2: "http://www.example.com"},
          // Define colors
          red = '#E20079', blue = '#009EE0', yel = '#FFFA00',
          // Assign colors to areas
          colors = {0: blue, 1: yel, 2: red},
          // Prepare container for hover colors
          hoverColors = {};
      (function () {
        // Build a ready-to-use hoverColors list
        areas.forEach(function(members, area) {
          members.forEach(function(state) {
            hoverColors[state] = colors[area];
          });
        });
      })();
      // Used in mouse enter and mouse leave handlers
      function toggleAreaHiglight(code, action){
        var vMap = $('#vmap');
        areas.forEach(function(members) {
          if(members.indexOf(code)>-1) {
            members.forEach(function(state) {
              if(state != code) vMap.vectorMap(action, state);
            });
          }
        });
      }
      // Initialize the map
      $('#vmap').vectorMap({
        map: 'usa_en',
        backgroundColor: '#383838',
        enableZoom: false,
        showTooltip: true,
        selectedColor: null,
        hoverColors: hoverColors,
        onRegionOver: function(event, code, region){
          toggleAreaHiglight(code, 'highlight');
        },
        onRegionOut: function(event, code, region){
          toggleAreaHiglight(code, 'unhighlight');
        },
        onRegionClick: function(event, code, region){
          var link = links[$(areas).map(function(i) {
            if(this.indexOf(code)>-1) return i;
          })[0]];
          if(link) window.open(link);
        }
      });
    });
    

    There are two parts which needs some explanation:

    • hoverColors: i'm just preparing in advance an object which will contain the association between the code of a state and the needed hover color. The result then looks like this:

      {
        ak: "#009EE0",
        al: "#FFFA00",
        ar: "#FFFA00",
        ... all other states
        wv: "#E20079",
        wy: "#009EE0"
      }
      
    • toggleAreaHighlight: why skipping the current region code in the toggle highlight function?

      if(state != code) $('#vmap').vectorMap(action, state);
      

      Highlighting and un-highlighting the current state (region) under the mouse pointer is already built-in, and and so, therefore, there is no need to handle it twice.

    BTW, an additional note:

    in your second area, you declared South Carolina two times, maybe this is a typo, but anyway, to avoid nasty unwanted side effects, each code must be just only once in the areas.