So far, in our interactive social map, we added markers in each location that we clicked on and opened up an InfoWindow with the tweet information. Our next step will be to enable multiple tweets to live inside our InfoWindow by adding a pagination system into our window.
To get through this recipe you must be knee deep into our holistic chapter. If you dropped in just now, it would be a good idea to go back to the start of this chapter as we are going to continue from where we left off in the previous recipe.
We are still in our JavaScript file and we will continue to add code and adjust our code to get multiple Twitter posts into our social map.
var searchLink = 'http://search.twitter.com/search.json?q='+ searchKeyWord+ '&geocode=' + geocode +"&result_type=recent&rpp=100";
TwitterMaker
marker the full array (changes highlighted in the code snippet). google.maps.event.addListener(map, 'click', function(e) {
//console.log(e.latLng);
var searchKeyWord = 'html5';
var geocode=e.latLng.lat() + "," + e.latLng.lng()+",50km";
var searchLink = 'http://search.twitter.com/search.json?q='+ searchKeyWord+ '&geocode=' + geocode +"&result_type=recent&rpp=100";
$.getJSON(searchLink, function(data) {
showTweet(data.results,e.latLng);
});
});
function showTweet(a,latLng){
if(!a) a = [{text:'No tweet found in this area for this topic'}];
//console.log(obj);
var marker = new TwitterMarker({
map: map,
position: latLng,
tweet: a,
title:a[0].text });
}
}
TwitterMarker
constructor to include our array and quick information on it, such as the total tweets and the current tweet we are in. We will need a way to identify our object, and as such, we will give it an ID as well (more on that in a few steps).function TwitterMarker(opt){ this.count = opt.tweet.length; this.crnt = 0; this.id = TwitterMarker.aMarkers.push(this); this.aTweets = opt.tweet; var strTweet = this.buildTwitterHTML(opt.tweet[0]) this.infoWindow = new google.maps.InfoWindow({ maxWidth:300, content:strTweet }); this.setValues(opt); this.infoWindow.open(this.map,this); google.maps.event.addListener(this, 'click', this.onMarkerClick); }
TwitterMarker
class:TwitterMarker.prototype = new google.maps.Marker();
TwitterMarker.aMarkers= [];
buildTwitterHTML
method, we want to add in back/next links that will be visible to users from InfoWindow:TwitterMarker.prototype.buildTwitterHTML = function(twt){ var str; if(twt.from_user_name){ str = "<span><img style='float: left' src='"+twt.profile_image_url+"' />"+ "<b>" +twt.from_user_name + "</b><br/><a href ='http://twitter.com/" + twt.from_user + "'>@"+twt.from_user+"</a><br/> " + twt.location + "</span>" + "<p>"+twt.text+"</p>"; if(this.count>1){ str+="<span style='absolute; bottom: 0; right: 0px; width:80px'>"; if(this.crnt!=0) str+="<a href='javascript:TwitterMarker.aMarkers["+(this.id-1)+"].prev();'><</a> "; str+= (this.crnt+1) + " of " + this.count; if(this.crnt<(this.count-1)) str+= "<a href='javascript:TwitterMarker.aMarkers["+(this.id-1)+"].next();'>></a> "; str+= "</span>" } }else{ str="The 50 Kilometer radius around this point did not message this value"; } return str; }
next
and prev
methods.TwitterMarker.prototype.next =function(){ this.infoWindow.close(); this.infoWindow.content = this.buildTwitterHTML(this.aTweets[++this.crnt]); this.infoWindow.open(this.map,this); return false; } TwitterMarker.prototype.prev =function(){ this.infoWindow.close(); this.infoWindow.content = this.buildTwitterHTML(this.aTweets[--this.crnt]); this.infoWindow.open(this.map,this); return false; }
Load the HTML file, and you should find a working InfoWindow that can accommodate up to 100 tweets per click.
Our first change was to change the number of results coming back from the Twitter search API. This change forced us to change the references in our code from referring directly to the first object returned to focus on the full results object and sending it to our TwitterMarker
constructor. This change created a few smaller changes in the flow of the information within the constructor as well.
Our goals are to create two buttons that will update our InfoWindow. This is an issue as we need a two-way connection between our marker and its InfoWindow. Until now, all our communication with the InfoWindow was one way. The easiest way for us to solve this problem and bypass the Google interface is to create a static array that will store all markers and refer to our static marker when we trigger buttons inside the InfoWindow
object. All we need to do is add a variable direction to our class name.
TwitterMarker.aMarkers= [];
By adding our variable directly into the TwitterMarker
class, we can now refer to it directly at any point and it will not get duplicated in our objects (as it's not part of the prototype). Now that we have an array, it's time for us to go back into our TwitterMarker
constructor and send a new reference to this array each time we create a new TwitterMarker
object. Another benefit we get out of doing this is that we automatically get a unique identifier (ID) for each marker as the returned number will always be a unique number for our needs.
this.id = TwitterMarker.aMarkers.push(this);
In this one line of code, we perform all of the tasks we talked about in the previous paragraph. The array push
method returns the new length of the array.
Now that we have a way to refer to our marker and have got an identifier, it's time for us to go back into the buildTwitterHTML
method and add into the rendered HTML two href
buttons that will trigger the right marker when the next/previous selections are clicked.
Before we delve into that, we want to check and validate that we have more than one Twitter message that came back; if there is none, there is no point in adding the new logic, and we would be introducing a bug if we had next/previous logic for an item that has only one item.
if(this.count>1){ }
By the following if
statement, we figure out whether we are currently in the first Twitter message, and if not we shall add the back button:
if(this.crnt!=0) str+="<a href='javascript:TwitterMarker.aMarkers["+(this.id-1)+"].prev();'><</a> ";
This might look like a huge mess but, if we ignore the HTML and focus on the actual JavaScript that will be triggered when the button is pressed, this is what we will get:
TwitterMarker.aMarkers["+(this.id-1)+"].prev();
The this.id-1
parameter will be replaced with the actual current number:
As this is rendered into a string to be parsed as HTML, the value that will be integrated into the HTML will be hardcoded. Let's see this in a real case to make it clear. The first array ID would be 0
, and as such the prev
button would look like this code statement:
TwitterMarker.aMarkers[0].prev();
Now the logic is starting to reveal itself. By grabbing the marker from the array that is our current element, all that is left for us to do is trigger the prev
method and let it take over.
The same logic happens for our other end. The only condition is that we are not in the last Twitter result and if not we call the next
method:
if(this.crnt<(this.count-1)) str+= "<a href='javascript:TwitterMarker.aMarkers["+(this.id-1)+"].next();'>></a> ";
There you have it! The core of our logic is in place.
If we wanted we could have created our InfoWindow by wrapping a <div>
tag with a unique ID and just called it and made direct updates to our content (try doing that by yourself as that would be a better solution). Instead, we are working with the limitations of the InfoWindow. As we cannot update the full bucket container while it's open, we need to close it to update it and then open it again. Thus our logic in both the next
and prev
methods is similar; both have a limitation on the change of the actual value that is being rendered.
TwitterMarker.prototype.next =function(){
this.infoWindow.close();
this.infoWindow.content = this.buildTwitterHTML(this.aTweets[++this.crnt]);
this.infoWindow.open(this.map,this);
return false;
}
TwitterMarker.prototype.prev =function(){
this.infoWindow.close();
this.infoWindow.content = this.buildTwitterHTML(this.aTweets[--this.crnt]);
this.infoWindow.open(this.map,this);
return false;
}
All the logic is the same and limited to the highlighted code snippet. If you aren't familiar with this shortcut, the ++
and --
operators when set before a variable, enable us to add/subtract 1 from it and update it before its value is sent on. Thus in one line, we can both change the number in the variable and send that newly created number to continue its tasks.
In the case of the next
method, we want to grab the next tweet, while for the prev
method, we want to grab the previous tweet.
3.138.174.95