How would you refactor this boolean parameter?
I’ve got this piece of code and I’d like to get rid of the boolean parameter. How would you do it? I have some ideas, but I’m looking for some alternate perspectives.
I’ve got this piece of code and I’d like to get rid of the boolean parameter. How would you do it? I have some ideas, but I’m looking for some alternate perspectives.
In Part 1 I showed how the server-side tweet retrieval and caching mechanism works for the .NET Twitter Stream on Managed Assembly. In this post, I’ll show you how the UI pulls the items and updates the list live.
Twitter streams tend to show the newest items at the top of the page which I don’t think is ideal for reading a live stream of tweets. I decided to build an interface that showed the newest tweets at the bottom of a list so that it would read more like a chat window. I wanted the list to automatically scroll to keep up with the new items, but if you scrolled up to start reading older items autoscoll would be disabled so you wouldn’t be constantly losing your place.
When a visitor hits the page a call is made to the /Refresh method described in Part 1. On the first request the last 100 cached tweets on the server are returned along with the ID of the most recent tweet, which is stored in a hidden field. On subsequent requests the value from the hidden field is included in the request to /Refresh so that only new tweets are returned and appended to the list. This minimizes the amount of traffic sent back and forth and the amount of work needed to append items to the list (just loop through the returned items and append the generated HTML).
Let’s start with the HTML needed:
<div id="statusContainer">
<table id="statuses" style="table-layout: fixed; overflow: hidden;">
</table>
</div>
<p>
Updates automatically every 60 seconds.
Auto scroll is
<span id="autoScrollOn">ON</span>
<span id="autoScrollOff" style="display: none;">OFF</span>
</p>
<%=Html.Hidden("lid", "") %>
There’s a couple inline styles but bare with me. There’s a certain amount of “get-it-done”-ness to the code (particularly the HTML generation later) but it’s not important, this is just an example that happens to be running great live :-)
There’s a lot of CSS involved, but the important style definitions to make the autoscrolling work are as follows:
#autoScrollOff { color: #f00; }
#autoScrollOn { color: #0f0; }
#statusContainer
{
height: 525px;
overflow: auto;
border: 1px solid #ccc;
margin: 5px 0;
}
#statuses
{
width: 100%;
border: none;
border-collapse: collapse;
}
There are two functions that make it happen. The first calls for the JSON and schedules itself to be called again in 60 seconds:
function getUpdates() {
$.getJSON('<%=Url.Action("Refresh")%>', { lid: $("#lid").val() }, refreshList);
window.setTimeout(getUpdates, 60000);
}
The other function is called when the JSON is retrieved (again, this should use client-side templating or something better than just string concats, but it doesn’t so get over it):
function refreshList(json) {
if (json.max_id != 0)
$("#lid").val(json.max_id);
$.each(json.results.reverse(), function(i, result) {
var html = "<tr class=\"status new\"><td class=\"avatar\"><a target=\"_blank\" href=\"http://twitter.com/" + result.UserName + "\"><img height=\"48\" width=\"48\" src=\"" + result.ProfileImageUrl + "\" align=\"left\" /></a></td>";
html += "<td><p><span class=\"user\"><a target=\"_blank\" href=\"http://twitter.com/" + result.UserName + "\">" + result.UserName + "</a></span> ";
html += result.Text + "</p><p class=\"meta\">" + result.RelativeTime + " from " + result.ClientLink;
if (result.IsReply) {
html += " <a href=\"http://twitter.com/" + result.InReplyToUser + "/statuses/" + result.InReplyToId + "\">in reply to " + result.InReplyToUser + "</a>"
}
html += "</p></td></tr>";
$("#statuses").append(html);
});
if (autoScroll) $("#statusContainer").scrollTo(99999);
}
We store the max ID returned to use for the next call. The tweet list is reversed to put new ones at the bottom (this could be handled server-side too), the HTML is built and appended to the table. At the end of the function we check to see if autoScroll is set and if so, scroll to a big number using the jQuery ScrollTo plugin.
To start things in motion, we call the getUpdates() function in document.ready() and attach the handlers to manage autoScroll state:
var autoScroll = true;
$(function() {
getUpdates();
$("#statusContainer").scroll(function() {
autoScroll = this.scrollTop + this.clientHeight == this.scrollHeight;
if (autoScroll) {
$("#autoScrollOn").show();
$("#autoScrollOff").hide();
}
else {
$("#autoScrollOff").show();
$("#autoScrollOn").hide();
}
});
});
autoScroll is defined outside of document.ready() so that’s available in all the calls to getUpdates().
There’s a similar method for retrieving the list of users currently being followed for the stream. Since the time I originally wrote this code I’ve started reading JavaScript: The Good Parts by Douglas Crockford so I’m a little ashamed of the JavaScript, but it does work well and that’s all I need for now.