tvalent2
tvalent2

Reputation: 5009

JavaScript to dynamically plot points on Raphael.js map

I'm using John Emerson's world map to plot some vacation destinations by lat/long. If I hard code everything I can hover over and click the dot, which will display the vacation title. However, since trying to dynamically plot my destinations by retrieving JSON, I can no longer click. Can any JavaScript experts help me figure out what I'm doing wrong?

Here's my code:

window.onload = function () {
  var current = null;
  var map = {};
  var m = {};       
  var attr = {
    fill: "#333",
    stroke: "#888",
    "stroke-width": .5,
    "stroke-linejoin": "round"
  };        
  var map = {};
  var R = Raphael("holder_570");
  render_map(R,map,attr);   
  for (var state in map) {                      
            map[state].color = Raphael.getColor();
            (function (st, state) {
      st[0].style.cursor = "pointer";
      st[0].onmouseover = function () {
        current && map[current].animate({fill: "#333", stroke: "#666"}, 300);
        // st.animate({fill: st.color, stroke: "#ccc"}, 300);
        R.safari();
        // current = state;
      };
      st[0].onmouseout = function () {
        st.animate({fill: "#333", stroke: "#666"}, 300);
        R.safari();
      };

      // st[0].onclick = function () {
      //   alert(state);
      // };
    })(map[state], state);
  }; // end for

  function lon2x(lon) {
      var xfactor = 1.5255;
      var xoffset = 263.58;
      var x = (lon * xfactor) + xoffset;
      return x;
  }
  function lat2y(lat) {
    var yfactor = -1.5255;
    var yoffset = 130.5;
    var y = (lat * yfactor) + yoffset;
    return y;
  }

  var city_attr = {
    fill: "#0f0",
    stroke: "none",
    opacity: .3
  };
  function plot(lat,lon,size) {
    size = size * .5 + 4;
    return R.circle(lon2x(lon), lat2y(lat), size).attr(city_attr);
  }


  var vacations = {};

  $.getJSON("/vacations_lat_long", function(data) {
    var datum, _i, _len, _results;
    _results = [];
    for (_i = 0, _len = data.length; _i < _len; _i++) {
      datum = data[_i];
      _results.push(vacations[datum.city] = plot(parseFloat(datum.latitude), parseFloat(datum.longitude), 1));
    }
    return _results;
  });

  // HARD CODED EXAMPLES
  // vacations.Nellysford        = plot(37.9069562,-78.8527841,1);
  // vacations.Charles_Town      = plot(39.2536975,-77.9335429,1);

  var current_city = null;
  var city_box = null;
  for (var city in vacations) {                      
            map[state].color = Raphael.getColor();
            (function (st, city) {
      st[0].style.cursor = "pointer";
      st[0].onmouseover = function () {
        current_city && vacations[current_city].animate({fill: "#0f0", opacity: .3}, 300);
        st.animate({fill: "#0f0", opacity: 1}, 300);
        R.safari();
        current_city = city;
      };
      st[0].onmouseout = function () {
        st.animate({fill: "#0f0", opacity: .3}, 300);
        R.safari();
      };

      st[0].onclick = function () {
        if (t = document.getElementById(city_box)) { t.style.display = "none"; }
        if (t = document.getElementById(city)) { t.style.display = "block"; }
        city_box = city;
      };


      if (t = document.getElementById(city)) {
          t.style.left = vacations[city].attr('cx') + 'px';
          t.style.top = vacations[city].attr('cy') -20 + 'px';
      }

    })(vacations[city], city);
  }; // end for

};

Where I'm having trouble is in this code:

$.getJSON("/vacations_lat_long", function(data) {
    var datum, _i, _len, _results;
    _results = [];
    for (_i = 0, _len = data.length; _i < _len; _i++) {
      datum = data[_i];
      _results.push(vacations[datum.city] = plot(parseFloat(datum.latitude), parseFloat(datum.longitude), 1));
    }
    return _results;
  });

As I said, the points are plotted but I can't see the opacity transition when hovering over the dots, nor can I see anything when clicking the dot.

Upvotes: 1

Views: 2717

Answers (1)

mmrobins
mmrobins

Reputation: 13795

It's fairly difficult to see this based on the info given, so here's a jsfiddle with a your example having the problem:

http://jsfiddle.net/mmrobins/wQYEf/19/

And here's the fix:

http://jsfiddle.net/mmrobins/wQYEf/18

It's really difficult to see, but the problem is simply that the jquery call is asynchronous, so it hasn't returned data by the time the code below setting up the click actions. So when you iterate through cities in vacations, vacations is actually empty.

The fix was simply to move all the code inside the getJSON callback so that it doesn't run until after the data has returned.

Upvotes: 3

Related Questions