﻿
// Code by www.mapchannels.com, June 2009 - you are free to use or modify the code in any way for your own use. 
// When you use this code please include a link to http://www.mapchannels.com on your page!

// References:
// http://code.google.com/apis/maps/documentation/v3/ 
// http://apiwiki.twitter.com/Twitter-Search-API-Method%3A-search
// http://blog.webandy.com/2009/04/20/auto-link-twitter-ruby-javascript.html


var map;
var geocoder;
var visibleInfoWindow = null;
var selectedCity = null;
var selectedTag = "";
var selectedRange = "100mi";

var cityList = [];
var tagList = [];

var maxTweets = 100;

var startCentre = new google.maps.LatLng(35.701359130802444,51.416015625);
var startZoom = 5;

var citiesSource =

    [   
    
        { name:"Ahvaz", lat:31.33369804043943, lng:48.71337890625, range:"100mi", colour:"blue" },
        { name:"Esfahan", lat:32.668569802309285, lng:51.66664123535156, range:"100mi", colour:"blue" },
        { name:"Bakhtaran", lat:34.34683765855365, lng:47.129974365234375, range:"100mi", colour:"blue" },
        { name:"Gorgan", lat:36.84775766525783, lng:54.41802978515625, range:"100mi", colour:"blue" },
        { name:"Kerman", lat:30.28871742623309, lng:57.0574951171875, range:"100mi", colour:"blue" },
        { name:"Mashhad", lat:36.30350540784278, lng:59.5623779296875, range:"100mi", colour:"blue" },
        { name:"Qom", lat:34.65015548393827, lng:50.876312255859375, range:"100mi", colour:"blue" },
        { name:"Rasht", lat:37.309014074275915, lng:49.57305908203125, range:"100mi", colour:"blue" },
        { name:"Shiraz", lat:29.59375955382993, lng:52.5201416015625, range:"100mi", colour:"blue" },
        { name:"Tabriz", lat:38.067554724225275, lng:46.27166748046875, range:"100mi", colour:"blue" },
        { name:"Tehran", lat:35.701359130802444, lng:51.416015625, range:"100mi", colour:"blue" },
        { name:"Zahedan", lat:29.485034019181064, lng:60.85052490234375, range:"100mi", colour:"blue" },

        { name:"Qatar", lat:25.453194979524866, lng:51.3995361328125, range:"100mi", colour:"gray" },
        { name:"Riyadh", lat:24.81166755546185, lng:46.746826171875, range:"100mi", colour:"gray" },
        { name:"Cairo", lat:30.031055426540206, lng:31.260223388671875, range:"100mi", colour:"gray" },
        { name:"Beirut", lat:33.8886289, lng:35.4954794, range:"100mi", colour:"gray" },
        { name:"Gaza", lat:31.426319456957188, lng:34.49432373046875, range:"100mi", colour:"gray" },
        { name:"Damascus", lat:33.5158, lng:36.2939, range:"100mi", colour:"gray" },
        { name:"Dubai", lat:25.271139, lng:55.307485, range:"100mi", colour:"gray" },
        { name:"Baghdad", lat:33.3157, lng:44.3922, range:"100mi", colour:"gray" },
        { name:"Amman", lat:31.9394, lng:35.9349, range:"100mi", colour:"gray" },
        { name:"Kabul", lat:34.5155, lng:69.1952, range:"100mi", colour:"gray" },

        { name:"London", lat:51.511092905004745, lng:-0.1256561279296875, range:"100mi", colour:"gray" },
        { name:"Paris", lat:48.86381134898788, lng:2.3236083984375, range:"100mi", colour:"gray" },
        { name:"Berlin", lat:52.52207036136366, lng:13.4088134765625, range:"100mi", colour:"gray" },
        { name:"Minsk", lat:53.9677874, lng:27.5765553, range:"100mi", colour:"gray" },
        { name:"Moscow", lat:55.754167897761, lng:37.61444091796875, range:"100mi", colour:"gray" },
        
        { name:"New York", lat:40.77430186363723, lng:-73.9874267578125, range:"100mi", colour:"gray" },
        { name:"Chicago", lat:41.879535, lng:-87.624333, range:"100mi", colour:"gray" },
        { name:"Los Angeles", lat:34.052187, lng:-118.243425, range:"100mi", colour:"gray" },
        { name:"Ottawa", lat:45.423494, lng:-75.697933, range:"100mi", colour:"gray" },

        { name:"Rio De Janeiro", lat:-22.9035393, lng:-43.2095869, range:"100mi", colour:"gray" },
        { name:"Mexico City", lat:19.410636, lng:-99.130588, range:"100mi", colour:"gray" },
        
        { name:"Lahore", lat:31.54505, lng:74.340683, range:"100mi", colour:"gray" },
        { name:"New Delhi", lat:28.635308, lng:77.22496, range:"100mi", colour:"gray" },
        { name:"Mumbai", lat:19.017656, lng:72.856178, range:"100mi", colour:"gray" },
        { name:"Beijing", lat:39.9081726, lng:116.3979471, range:"100mi", colour:"gray" },
        
        { name:"Bangkok", lat:13.7234186, lng:100.4762319, range:"100mi", colour:"gray" },
        { name:"Manila", lat:14.6010326, lng:120.9761599, range:"100mi", colour:"gray" },
        { name:"Jakarta", lat:-6.211544, lng:106.845172, range:"100mi", colour:"gray" },

        { name:"Canberra", lat:-35.28204, lng:149.12858, range:"100mi", colour:"gray" },
        { name:"Tokyo", lat:35.68184060244453, lng:139.75914001464844, range:"100mi", colour:"gray" }
    ];

var tagList = [ "#IranElection", "#FreeIran", "#Iran", "#Tehran", "#Mousavi", "#Ahmadinejad", "#gr88" ];


// *** City ***
function City()
{
    this.name = "";
    this.point = null;
    this.range = "100mi";
    this.colour = "blue";

    this.marker = null;
    this.infowindow = null;
}

City.prototype.createMarker = function()
{
    var city = this;
    
    var marker = new google.maps.Marker({ position: this.point, map: map, title:this.name });
    this.marker = marker;    
  
    google.maps.event.addListener(marker, "click", function() 
    {
        city.clickMarker();
    });
}

City.prototype.clickMarker = function()
{
    selectedCity = this;
    
    if (visibleInfoWindow)
    {
        visibleInfoWindow.close();
    }

    eid("locationText").value = this.name;
    
    if (this.marker)
    {
        if (!this.infowindow)
        {
            this.infowindow = new google.maps.InfoWindow({ content: this.name });
        }
        
        this.infowindow.open(map, this.marker);
        visibleInfoWindow = this.infowindow;
    }

    updateTweets();
}

function clickLocation(a)
{
     var city = cityList[a];
     city.clickMarker();
     
     if (a == 0)
     {
        var centre = new google.maps.LatLng(0,0);
        map.set_center(centre);
        map.set_zoom(1);
     }
}

function displayLocation()
{
    // un-comment to display current latlng below map

    /*
    var centre = map.get_center();
    var txt = "<i>lat:" + centre.lat() + ", lng:" + centre.lng() + "</i>";
    
    eid("locationDiv").innerHTML = txt; 
    */    
}

// *** Tag ***
function clickTag(a)
{
    var tag = tagList[a];
    eid("tagText").value = tag;
    
    selectedTag = tag;
    
    updateTweets();
}

// *** Buttons ***
function setLocation()
{
    var cityname = eid("locationText").value;

    if (geocoder) 
    {
        geocoder.geocode( { 'address': cityname}, function(results, status) 
        {
            if (status == google.maps.GeocoderStatus.OK) 
            {
                if (status != google.maps.GeocoderStatus.ZERO_RESULTS) 
                {
                    var latlng = results[0].geometry.location;
                    map.set_center(latlng);
                    
                    selectedCity = new City();
                    selectedCity.name = cityname;
                    selectedCity.point = latlng;
                    
                    updateTweets();                                        
                }
                else 
                {
                    alert("No results found");
                }
            }
            else 
            {
                alert("Geocode was not successful for the following reason: " + status);
            }
        });
    }
}

function setTag()
{
    selectedTag = eid("tagText").value;
    updateTweets();
}

// *** initialize ***
function initialize() 
{
    geocoder = new google.maps.Geocoder();

    // create map
    var mapOptions = 
    {   center: startCentre,
        zoom: startZoom,
        mapTypeId: google.maps.MapTypeId.TERRAIN,
        scaleControl:true, 
        mapTypeControl: true,
        mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
        navigationControl: true,
        navigationControlOptions: {style: google.maps.NavigationControlStyle.DEFAULT}
    };
    map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);

    google.maps.event.addListener(map, "center_changed", function()
    {
        displayLocation();
    });

    google.maps.event.addListener(map, "click", function()
    {
        if (visibleInfoWindow)
        {
            visibleInfoWindow.close();
        }
    });

    var html = "";

    // cities
    if (true)
    {    
        var city = new City();
    
        city.name = "All";
        city.point = null;
        cityList[0] = city;
        
        html += "<a href='javascript:clickLocation(0)' style='color:black;font-weight:bold'>All</a>&nbsp; ";
    }
    
    for (var i=1; i<=citiesSource.length; i++)
    {
        var city = new City();
        
        var src = citiesSource[i-1];
        city.name =  src.name;
        city.point = new google.maps.LatLng(src.lat, src.lng);
        city.range = src.range;
        city.colour = src.colour;
        city.createMarker();
        
        html += "<a href='javascript:clickLocation(" + i + ")' style='color:" + city.colour + "'>" + city.name + "</a>&nbsp; ";
        
        cityList[i] = city;
    }
    
    selectedCity = cityList[0]; // 'all'
    
    eid("locations").innerHTML = html;
    
    // tags
    html = "";
    for (var i=0; i<tagList.length; i++)
    {
        html +=  "<a href='javascript:clickTag(" + i + ")'>" + tagList[i] + "</a>&nbsp; ";
    }    
    eid("tags").innerHTML = html;
    
    selectedTag = tagList[0];
    eid("tagText").value = selectedTag;
  
    displayLocation();
    updateTweets();
}

function eid(a)
{
    return document.getElementById(a);
}

function moreTweets()
{
    var script = document.createElement('script');
    document.body.appendChild(script);

    searchUrl = "http://search.twitter.com/search.json" + moreUrl + "&callback=cbTweets";    
    
    // alert(searchUrl);
    
    script.src = searchUrl;
}

// *** Search ***
var searchUrl = "";
var moreUrl = "";

function cbTweets(a) 
{
    var tweets = a.results;
    
    if (typeof(a.next_page) != "undefined")
    {
        moreUrl = a.next_page;
        eid("more").innerHTML = "<a href='javascript:moreTweets()'>More</a>";
    }
    else
    {
        moreUrl = "";
        eid("more").innerHTML = "";
    }
    
    var html = "<table cellspacing=0 cellpadding=8 style='width:100%'>";
    for (var i=0; i<tweets.length; i++)
    {
        var tweet = tweets[i];            

        var text = tweet.text;
        
        // convert tweet links using regex - ref: http://blog.webandy.com/2009/04/20/auto-link-twitter-ruby-javascript.html
        if (text.search(/(https?:\/\/[-\w\.]+:?\/[\w\/_\.]*(\?\S+)?)/) > -1) 
        {
            text = text.replace(/(https?:\/\/[-\w\.]+:?\/[\w\/_\.]*(\?\S+)?)/, "<a target='_blank' href='$1'>$1</a>")
        }

        if(text.search(/@\w+/) > -1)
        {
            text = text.replace(/(@)(\w+)/g, "$1<a target='_blank' href='http://twitter.com/$2'>$2</a>");
        }
        
        html += 
            "<tr valign='top'><td>" +
            "<div style='float:left;padding-right:8px'><a target='_blank' href='http://twitter.com/" + tweet.from_user + "'>" +
            "<img src='" + tweet.profile_image_url + "' width=48 height=48 border=0 title='" + tweet.from_user + "' /></a></div>" +
            text + "<div style='color:gray' title='" + tweet.created_at + "'><i>" + relative_time(tweet.created_at) + "</i></div> " + 
            "</td></tr>";
    }
    
    if (tweets.length == 0)
    {
        html += "No tweets";
    }
    html += "</table>";
    
    var len = eid("tweets").innerHTML.length;
    if (len < 20)
    { 
        eid("tweets").innerHTML = html;
    }
    else
    {
        eid("tweets").innerHTML += html;
    }
}

function updateTweets()
{
    eid("tweets").innerHTML = "Loading tweets ...";
    moreUrl = "";
    eid("more").innerHTML = "";    
    
    var script = document.createElement('script');
    document.body.appendChild(script);
    
    if (selectedTag.substr(0,1) == "#")
    {
        selectedTag = "%23" + selectedTag.substr(1);
    }
    
    if (selectedCity.point)
    {
        var x = selectedCity.point.lng();
        var y = selectedCity.point.lat();
        
        searchUrl = 
            "http://search.twitter.com/search.json?callback=cbTweets" +
            "&geocode=" + y + "%2C" + x + "%2C" + selectedCity.range +
            "&q=" + selectedTag;
            "&count=" + maxTweets;
    }
    else
    {
        searchUrl = 
            "http://search.twitter.com/search.json?callback=cbTweets" +
            "&q=" + selectedTag;
            "&count=" + maxTweets;
    }
    
    searchUrl += "&noCacheIE=" + (new Date()).getTime();
    
    script.src = searchUrl;
}

// ref: http://macthemes2.net/forum/viewtopic.php?pid=462241
function relative_time(time_value) 
{
     var created_at_time = Date.parse(time_value.replace(" +0000",""));
     var relative_time = ( arguments.length > 1 ) ? arguments[1] : new Date();
     var wordy_time = parseInt(( relative_time.getTime() - created_at_time ) / 1000) + (relative_time.getTimezoneOffset()*60);

       if ( wordy_time < 59 ) {
         return 'less than a minute ago';
         }
       else if ( wordy_time < 89) {
         return 'about a minute ago';
         }
       else if ( wordy_time < 3000 ) {         // < 50 minutes ago
         return ( parseInt( wordy_time / 60 )).toString() + ' minutes ago';
         }
       else if ( wordy_time < 5340 ) {         // < 89 minutes ago
         return 'about an hour ago';
         }
       else if ( wordy_time < 9000 ) {          // < 150 minutes ago
         return 'a couple of hours ago'; 
         }
       else if ( wordy_time < 82800 ) {         // < 23 hours ago
         return 'about ' + ( parseInt( wordy_time / 3600 )).toString() + ' hours ago';
         }
       else if ( wordy_time < 129600 ) {       //  < 36 hours
         return 'a day ago';
         }
       else if ( wordy_time < 172800 ) {       // < 48 hours
         return 'almost 2 days ago';
         }
       else {
         return ( parseInt(wordy_time / 86400)).toString() + ' days ago';
         }
    }



