Coding away from the keyboard

Whilst working on a program to automatically generate mazes, I realised that most of my spare time for this kind of thing is either when watching TV, or when I’m away from home, such as on the park and ride bus to and from work. As I was looking to solve the problem using JavaScript/HTML there is no compiler involved, so some kind of editor app for my phone would be ideal. Sure enough there are several in the App Store, I settled on Expresso HTML, well because it looks nice, has some useful shortcuts to characters such as “<", has a handy inbuilt browser to preview my efforts – oh and it's free.

20120115-162704.jpg
Coding on the go is fairly tough going, the virtual keyboard obscures half of the screen and doesn’t allow tabs (double space indentation!), but it is easy to switch between preview and editor mode, and you can work on multiple files. Ideal for small projects and experimenting on the go – it was enough to get my maze generator finished and working, details of how I got on to follow in a future post. If it had an in-built FTP client it would be great for making for emergency corrections.

Infinite scrolling with an ASP.net webform, jQuery, and a little bit of code

Infinite scrolling presents your content as one long page – as you read (scroll) toward the bottom of the content some more loads in below automatically (and hopefully seamlessly). This allows your site visitor to focus on content without being distracted by enforced navigation concepts such as paging. It also means you only serve as much content as the user wants to see, which is espacially useful in today’s increasingly mobile world. Twitter and Facebook are good examples of sites that do this well.

This post aims to give a hopefully simple example of how to achieve this using the following basic ingredients:

  • ASP.net/C# 4.0 (I’m using Visual Web Developer Express)
  • An ASP.net webform
  • A ScriptMethod
  • jQuery and a bit of JavaScript
  • Some data – in this case a list of pretend blog posts

How it works

The webform will display the first ten blog posts. When the user scrolls to the bottom of the page some JavaScript will call a method to return the next ten items. These are then appended to the bottom of the page. When the user scrolls to the bottom of that the process repeats until there are no blog posts left.

This is simplified for us by the use of a ScriptMethod, which is like a WebMethod in a web service, except you place it in a normal ASPX page as a static method decorated with the ScriptMethod attribute (code example below). ASP.net then kindly provides a nice JavaScript proxy for us to call this with one line of code. I’m then using jQuery to simplify the process of adding the resulting array of BlogPost items to the page.

Blog Post Repository

First things first, we need some data to display and so I have created a static class BlogPostRepository which provides access to a list of made up BlogPost items:


public class BlogPost
{
	public string Title { get; set; }
	public string Summary { get; set; }

	public BlogPost(string title, string summary)
	{
		Title = title;
		Summary = summary;
	}
}

public static class BlogPostRepository
{
	static List<BlogPost> posts;

	static BlogPostRepository()
	{
		posts = new List<BlogPost>();

		for (int i = 1; i <= 200; i++)
		{
			posts.Add(new BlogPost(string.Format("Post number {0}", i),
				string.Format("Discover my thoughts on the number {0}.", i)));
		}
	}

	public static List<BlogPost> GetPosts(int startAt, int howMany)
	{
		return (from p in posts
			select p).Skip(startAt).Take(howMany).ToList();
	}
}

The code behind page

The code behind for the web page is straightforward – bind the first ten posts to a ListView control during Page_Load, and the ScriptMethod GetPosts will return additional blog posts to the page on request:

protected void Page_Load(object sender, EventArgs e)
{
	if (!IsPostBack)
	{
		lvItems.DataSource = BlogPostRepository.GetPosts(0, 10);
		lvItems.DataBind();
	}
}

[System.Web.Services.WebMethod()]
[System.Web.Script.Services.ScriptMethod()]
public static List<BlogPost> GetPosts(int startAt, int howMany)
{
	return BlogPostRepository.GetPosts(startAt, howMany);
}

Note that GetPosts is decorated as a WebMethod and also a ScriptMethod. It also needs to be static.

The mark up

The key to making Script Methods work is the <asp:ScriptManager> which needs to have EnablePageMethods set to “true”:

<asp:ScriptManager runat="server" ID="ScriptManager1" EnablePageMethods="true">
</asp:ScriptManager>

This ensures that the necessary JavaScript helper methods are available.

Next up is a ListView control which I really like because of the control it offers over the output in your page. This takes care of the initial output of blog posts:

<asp:ListView runat="server" ID="lvItems">
	<LayoutTemplate>
		<div id="container">
			<asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
		</div>
	</LayoutTemplate>
	<ItemTemplate>
		<div class="post">
			<h2>
				<%# Eval("Title") %></h2>
			<p>
				<%# Eval("Summary") %></p>
		</div>
	</ItemTemplate>
	<AlternatingItemTemplate>
		<div class="post shade">
			<h2>
				<h2>
					<%# Eval("Title") %></h2>
				<p>
					<%# Eval("Summary") %></p>
		</div>
	</AlternatingItemTemplate>
</asp:ListView>       

You will notice that each blog post has a container DIV with a class of “post”, and that they are all held within a container DIV with an ID of “container”. Alternate posts have a shaded background thanks to some CSS and the additional “shade” class. The next thing is to add the JavaScript:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
    $(window).scroll(function () {
        if ($(window).scrollTop() == $(document).height() - $(window).height()) {
            GetPosts();
        }
    });
});

function GetPosts() {
    var howMany = 10;
    var startAt = $(".post").size();
    PageMethods.GetPosts(startAt, howMany, OnGetPostsComplete);
}

function OnGetPostsComplete(posts) {
    for (var i = 0; i < posts.length; i++) {
        var shade = (i % 2) != 0 ? " shade" : "";
        $("#container").last().append("<div class=\"post" + shade + "\"><h2>" +
                            posts[i].Title + "</h2><p>" +
                            posts[i].Summary + "</p></div>");
    }
}
</script>

Lets look at the script above. First I use jQuery to attach a function to the scroll event of the window. This will fire whenever the user scrolls to the bottom of the page, and simply calls the GetPosts method.

GetPosts uses jQuery to get a count of items in the page with the class “post”. This will equal the number of blog posts output so far. I can then call a JavaScript method provided for us by ASP.net because the GetPosts method in our code behind is decorated as a ScriptMethod. So PageMethods.GetPosts takes the same parameters as the C# code, plus in addition the name of the method to call when the asynchronous web call has completed – i.e. when we have the results of the call, in this case OnGetPostsComplete

OnGetPostsComplete takes the array of BlogPost items returned by the ScriptMethod and appends them to the end of the items already in the container DIV which holds all of the blog post DIVs. For effect I’m adding the “shade” class to alternate post items which I have defined in CSS to give them a different background colour.

What next

I haven’t tried this with a database as a data source so speeds will vary. When using the in-memory repository there was hardly a noticable delay at all in the new items being displayed. You might want to add an AJAX style “spinner” graphic to show when loading is occurring. This can easily be achieved using a hidden DIV and the jQuery toggle() method, e.g. $("#loading").toggle();. Toggle it on in GetPosts, and off again in OnGetPostsComplete.

HexaClock

20120121-070519.jpg

A little while back a friend of mine Anthony Casey decided to make an iOS friendly HTML5/CSS3 based clock similar to the Flash based The Colour Clock. This is a digital clock where the background colour changes with every second of the day. You can view the completed HexaClock here, though you will need a HTML5 browser (no Internet Explorer 8 or below I’m afraid).

Anthony is a whizz with all things HTML/CSS, and asked me if I could help out by coming up with some JavaScript to make the clock change colour and tell the time.

Figuring out which colour to show

First things first, how do I make every second of the day a different colour? As we know the current time of day is made up of three parts, hours (0-23), minutes (0-59) and seconds (0-59). Luckily for us colours on the web are also made up of three parts, combinations of red, green and blue (known as RGB). The amount of each colour to use is a value between 0 and 255, e.g. 255 red is solid red, 0 red is no red at all, and 128 red is a dark maroon type colour. Using this knowledge we can create colours and shades, for example:

Red – R:255 G:0 B:0
White – R:255 G:255 B:255
Black – R:0 G:0 B:0
Yellow – R:255 G:255 B:0
Purple – R:195 G:48 B:255

It’s kind of like the opposite of mixing paint – here mix lots of each colour and you end up with white instead of a mucky browny black colour. There are plenty of sites out there that explain RGB colours in more detail.

How much of each colour to use

The amount of red to use maps to the hour of the day, green to the minute in the hour, and blue to the second in the minute. Using the actual value of hour, minute and second would result in lots of dark colours as we would never get a number higher than 59, so instead we will figure it out as a proportion of 255:

Red = (hour / 24) * 255
Green = (minute / 60) * 255
Blue = (second / 60) * 255

Making it tick

With the colour problem sorted the next step is to make the clock update every second. I created a “tick” function to show the current time and the appropriate background colour. To make it update once a second the JavaScript setTimeout function was used to call “tick” again after 1000 milliseconds.

Web browsers prefer their colour values represented in hexadecimal so the numbers need converting first. After first looking at writing a small decimal to hex conversion function I realised there was no need as I could use a nice feature of JavaScript to specify which number base to use when converting a number to a string, e.g. 15.toString(16) = “f”. This should actually be “0f” so the fix2 function tidies up any one digit hex values.

Here is the full code:

function hexClock(bodyId, clockId) { this.body = document.getElementById(bodyId); this.clock = document.getElementById(clockId); this.running = false; this.fix2 = function (n) { return (n < 10) ? "0" + n : "" + n; } this.tick = function () { if (!this.running) return; var now = new Date(); var h = now.getHours(); var m = now.getMinutes(); var s = now.getSeconds(); var hexH = Math.round((h/24) * 255).toString(16); var hexM = Math.round((m/60) * 255).toString(16); var hexS = Math.round((s/60) * 255).toString(16); this.body.style.backgroundColor = "#" + this.fix2(hexH) + this.fix2(hexM) + this.fix2(hexS); this.clock.innerHTML = this.fix2(h) + ":" + this.fix2(m) + ":" + this.fix2(s); setTimeout(function(me) { me.tick(); }, 1000, this); } this.start = function () { this.running = true; this.tick(); } this.stop = function () { this.running = false; } } // this bit runs when the page loads function init() { var clock = new hexClock("body", "clock"); clock.start(); }

Probably not the best bit of JavaScript that you will ever see but it does the job. At some point I might rewrite it using the Prototype approach.