Cool Interactive Map

I added a new interactive map out on NBNW and I think it’s pretty cool. That’s one person!

If you check it out and like it, you can use it too (I’ll give you everything below). Everything is free including the source where I got started (RaphaelJS check it out, very powerful).

Hover your mouse over a country and if available, the average net worth results will appear for all users in that country.

Hover your mouse over a country and if available, the average net worth results will appear for all users in that country.

To play with the map, the only real requirement is that you have a fairly modern browser.  I use HTML5 features that might not work properly in older browsers. Oh, sorry, one more thing, it’s a pretty large map, like 1000 pixels wide, so you might do some scrolling on a small screen.

For you techies, here’s the guts you’ll need (feel free to right-click and View source on my site and take any of that you need). In short, I load my custom database data (just a country name with an average net worth) into a two dimensional Javascript array by parsing the results of an Ajax call. Then when I hover over a country on the map, I pass the country name into my custom array looking for the average net worth.

First, download this from github:

https://raw.github.com/DmitryBaranovskiy/raphael/master/raphael-min.js

Then, download this from Raphael:

http://raphaeljs.com/world/world.js

Ok, so now it’s going to look like I threw up on the page and I sort of did. However, keep following past this main block and the rest will make sense. After that, back into this main block and it too will make sense.

<script src="/js/vendor/raphael-min.js"></script>
<script src="/js/vendor/world.js"></script>
<script>
Raphael("forworldmap", 1000, 400, function () {
var r = this;
r.rect(0, 0, 1000, 400, 10).attr({
    stroke: "none",
    fill: "0-#9bb7cb-#adc8da"
});
var over = function () {
    this.c = this.c || this.attr("fill");
    this.stop().animate({fill: "#bacabd"}, 500);
},
    out = function () {
	this.stop().animate({fill: this.c}, 500);
    };
r.setStart();
var hue = Math.random();
var myCountryArray = new Array();
for (var country in worldmap.shapes) {
    // var c = Raphael.hsb(Math.random(), .5, .75);
    // var c = Raphael.hsb(.11, .5, Math.random() * .25 - .25 + .75);
     var myRPath = r.path(worldmap.shapes[country]).attr({stroke: "#ccc6ae", fill: "#f0efeb", "stroke-opacity": 0.25});
     myCountryArray[myRPath.id] = worldmap.names[country];
     myRPath.hover(function() {
	showNetWorthTooltip(myCountryArray[this.id]);
     });
}
var world = r.setFinish();
world.hover(over, out);
// world.animate({fill: "#666", stroke: "#666"}, 2000);
world.getXY = function (lat, lon) {
    return {
	cx: lon * 2.6938 + 465.4,
	cy: lat * -2.6938 + 227.066
    };
};
world.getLatLon = function (x, y) {
    return {
	lat: (y - 227.066) / -2.6938,
	lon: (x - 465.4) / 2.6938
    };
};
var latlonrg = /(\d+(?:\.\d+)?)[\xb0\s]?\s*(?:(\d+(?:\.\d+)?)['\u2019\u2032\s])?\s*(?:(\d+(?:\.\d+)?)["\u201d\u2033\s])?\s*([SNEW])?/i;
world.parseLatLon = function (latlon) {
    var m = String(latlon).split(latlonrg),
	lat = m && +m[1] + (m[2] || 0) / 60 + (m[3] || 0) / 3600;
    if (m[4].toUpperCase() == "S") {
	lat = -lat;
    }
    var lon = m && +m[6] + (m[7] || 0) / 60 + (m[8] || 0) / 3600;
    if (m[9].toUpperCase() == "W") {
	lon = -lon;
    }
    return this.getXY(lat, lon);
};

try {
    navigator.geolocation && navigator.geolocation.getCurrentPosition(function (pos) {
	r.circle().attr({fill: "none", stroke: "#f00", r: 5}).attr(world.getXY(pos.coords.latitude, pos.coords.longitude));
    });
} catch (e) {}
var frm = document.getElementById("latlon-form"),
    dot = r.circle().attr({fill: "r#FE7727:50-#F57124:100", stroke: "#fff", "stroke-width": 2, r: 0}),
    // dot2 = r.circle().attr({stroke: "#000", r: 0}),
    ll = document.getElementById("latlon"),
    cities = document.getElementById("cities");
});
</script>

In that code above, it’s all right off Raphael. I only changed a few lines to create a new array for myself and call my own Javascript function on a mouse hover event.

var myRPath = r.path(worldmap.shapes[country]).attr({stroke: "#ccc6ae", fill: "#f0efeb", "stroke-opacity": 0.25});
myCountryArray[myRPath.id] = worldmap.names[country];
myRPath.hover(function() {
    showNetWorthTooltip(myCountryArray[this.id]);
});

And of course, here’s my custom code

//this var will hold all country data from initial ajax call
var mycountryarray = new Array();

$(document).ready(function(){
doLoadCountriesData();
});
function doLoadCountriesData()
{
	var sessionKey = "countriesInSession";
	//if browser supports session storage, try to use it
	if (sessionStorage) {
		var sessionValue = sessionStorage.getItem(sessionKey);
		if (sessionValue) {
			mycountryarray = $.parseJSON(sessionValue);
			return true; // We just avoided one ajax request
		}
	}
	//browser doesn't support session storage or the session var is empty, go get posts
	$.ajax({
		url: 'GetCountryAvgNetWorth.php',
		type: 'GET',
		cache: 'false',
		success: function(jsonresponse) {
			//if sessionStorage supported, save response in session
			if (sessionStorage) {
				mycountryarray = $.parseJSON(jsonresponse);
				sessionStorage.setItem(sessionKey, jsonresponse);
			}
		},
		error: function(xhr) {
			// handle errors
		},
	});
	return true;
}
function showNetWorthTooltip(country) {
	if (!(mycountryarray)) {
		doLoadCountriesData();
	}
	if (mycountryarray[country]) {
		$("#forworldmapcomment").html("Average net worth for " + country + " is $" + ReplaceNumberWithCommas(mycountryarray[country]));
	} else {
		$("#forworldmapcomment").html("Average net worth for " + country + " is unavailable");
	}
}
function ReplaceNumberWithCommas(yourNumber) {
	//Seperates the components of the number
	var n= yourNumber.toString().split(".");
	//Comma-fies the first part
	n[0] = n[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
	//Combines the two sections
	return n.join(".");
}
Advertisements
Leave a comment

5 Comments

  1. Hi Scott,

    Thanks for following my blog. I must admit that yours is a foreign language to me, but I will send my husband over– he has all the computer genes in the family and I just limp along. My favorite bit from your bio: “I like to humiliate myself for the entertainment benefit of my children (while they are still young enough to care and think it’s funny).” This means you understand the higher calling of being a dad. And just so you know, my kids are 20 and 16 and my husband is STILL embarrassing/entertaining them, to groans of “oh, Daaaad.” They would wonder what was wrong if he stopped.

    Reply
    • Hahaha, that cracked me up!! I like this guy! He’s my speed. Well, I have a feeling I’ll be the same way. They’ll know something is terribly wrong if I don’t! Oh, and I have the most random, super plainest looking blog you’ve ever seen. Seriously, a grey background color? I mean, come on, that’s boring. But I have a super random mix of corndogs and code…whatever comes to mind. Apologies in advance!

      Reply
  2. Pretty Cool!
    Sadly only got US and Canada 😦

    Reply
    • Yea, I hear ya, we got a few stragglers in there too, France and India I think…actually there are a few more, I might create a list if I have time. Thanks for the feedback.

      Reply
  1. Your Mouse Is A Magician | about ss

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: