Sunday, 26 April 2009

ASP.NET MVC User Controls on Master Pages

NOTE: I was originally going to post the investigation into the User Control/Master Page problem AND the User Controls code in one post. However, I thought it would possibly be a bit confusing so will post separately. This explains why the lab code is called “mvc-versionedfiles”.

I am real new to MVC. Up to this point I have found it to be quite pleasurable, I really liked the separation of concerns, the conventions and the testability. Something was bound to cause a bump in the road, and I finally hit it.

The Problem

I spoke to a couple of guys (@JeremySkinner and @robinem) at WebDD09 about this problem. What I was trying to accomplish was appending the file version of my CSS/Javascript files automatically to the LINK/SCRIPT elements in the HTML within the ASP.NET Master Page. For example:

   1: <link rel="Stylesheet" type="text/css" href="site.css?1.00">

Why Bother?

The reason is this, many browsers are very aggressive with the caching of CSS and Javascript files. And perhaps rightly so, in most cases once deployed they hardly change. However, this is not ALWAYS the case, so when they do, it can be a pain in the ass since there is not a great deal we can do about it at the server side. When the page is rendered, the user will simply get the cached version of the CSS/Javascript, warts and all.

Appending the version of the file to the path of the file is a nice little hack, since the browser will interpret it as a completely different GET request, meaning it will download a new copy of the file if the version number is different. The obvious downside to this is the user will have more than one file on their machine, but at a few KB, it’s not a real problem.

So Where Does the User Control Come In?

What I wanted to do was create a User Control that would encapsulate the rendering of the appropriate tag. I know similar things can be done via Subversion and other version control systems but I wanted to avoid that since it is an application requirement, in my opinion the solution to it should be contained within the application.

How Would You Do It In WebForms?

I would simply create a User Control and chuck some code in the code-behind to do the version-checking on the file, override the Render method and jobs a “good-un” right? Sure, it may not be excellent programming practice, but it is quick and easy, which is what WebForms is all about.

What’s Different in MVC?

We want to separate our concerns. This is pretty simple, we have:

  • versionedFilesThe Model which is where the “brains” of the application is. In this context this is where we need to figure out the version of the file.
  • The View or the presentation of the model. This is obviously the HTML output of the LINK/SCRIPT tags.
  • The Controller the dude in the thick of it all that gets the data from the model and passes it to the view to get them hooked up.

Why Is That So Hard? That’s Basic MVC!

Good point, where it gets really interesting is that we want to use the User Controls in Master Pages. Master pages are really “partial views” that are mashed together with content pages at run time, so the controller does not actually get the chance to explicitly create its own “Master Page Model Data”. So the fun begins..

Attempted Solutions

Be warned, some of these were simply me trying in vain with little forethought!

Lab 01 - What the MS MVC Guys Say:" “ViewData”

My obvious first port-of-call was the ASP.NET MVC site. Where I came across this tutorial. The tutorial isn’t all bad, and covers all angles, such as what the problems are. However, the proposed solution involves passing stuff directly to the ViewData dictionary using string values as the keys. This is done within a base controller that all other controllers inherit from. While it works, I really, really have issues with using “magic strings” to access the data. They can be error prone and a pain in the ass since you lose Intellisense support. Based on this, I decided to look for alternate avenues.

Code based on this tutorial can be found in the sample code. Note the following:

  • The Master Page has to reference the ViewData items by string key.
  • The ViewData[“masterPage”] element is populated by the abstract ViewDataBaseController class.
  • The content base is strongly typed, and accesses it’s content via the Model property as normal.

Lab 02 – Master Model and Typed Master Page

Another approach I came across this on StackOverflow (thanks to @JeremySkinner). I thought this looked interesting because it appears to have all the benefits of being strongly-typed as well as allowing you to segregate the “Master Page Model”.

Check out the sample code, noting the following:

  • Our controller does not inherit from an abstract base controller (good in case we forget).
  • We have a MasterModel model that simply returns the data we are interested in as properties. This has been marked as abstract since we can never have a Master Page on it’s own, likewise we should never have the Master Model on its own.
  • The master page is now strongly typed to the MasterModel class. This allows us to simply get the data from our MasterModel with Intellisense and type support.
  • We have a basic implementation of the MasterModel for our content pages, aptly called “BasicModel” which does nothing.

Now, the problem is that we need to instantiate the BasicModel in order to spin up the base MasterModel data. If we are using the standard code in the controller to return the default view in the controller:

   1: public ActionResult Index()
   2: {
   3:     return View();
   4: }

Then we get issues because the MasterModel that is referenced in the master page has not been initialised. This makes sense because we have not told the controller to do it’s job and get the model data, so we can easily fix this by altering the code to add the BasicModel to the View’s model:

   1: return View(new MasterModelContent());

Which works, but we are back to the position of “oh crap we must remember to do this” – which I try to avoid like the plague.

Lab 03 - Master Model with Abstract Controller

OK, so the previous solution was looking pretty good, so I wanted to investigate other avenues before writing it off. The problem is that we needed to always keep repeating ourselves in our controller methods to add create the BasicModel. We want to avoid having to always pass the Model data to every View (even if the view has no Model itself) – so why don’t we create a base controller to handle this for us?

Review the sample code again, note we have added an BaseController, overriding the View method with the following code:

   1: if (model == null || !(model is MasterModel))
   2:     model = new BasicModel();
   3:  
   4: return base.View(
   5:     viewName, masterName, model);

So here we have basically encapsulated our previous problem. If there is no subclass of MasterModel passed, then create one and use that.

Straight-out of the box, this works nicely. But those on the ball will realise this is in the “Attempted Solutions” section, so where did it go wrong?

The problem came for me when I tried integrating it in to my site (specifically the contact form). When the form was being loaded, it would fall over since the contact form was strongly-typed and bound to the contact form model:

   1: [AcceptVerbs(HttpVerbs.Post)]
   2: public ActionResult Index([Bind]ContactForm form)
   3: {
   4:     return View();
   5: }

This would then fail since when we browse to the form, the BaseController will see that we do not yet have a model and then go ahead and add a new BasicModel to the model data. App go BOOM!.

formFail

Now, I totally admit here that this could be due to a complete lack of grok, knowledge/understanding of the framework on my part. But I could not work out for the life of me figure out a way in which I could get things to spin up as requested, without messing with the default behaviour in any way.

If you know a way to make this work, then please comment and let me know! I actually like this method since everything is strongly typed and would love to get over this last hurdle!

What I Went With – ViewData Wrapper Extension Methods

So at this point, I was tired, annoyed at myself for not cracking it and just wanted my bloody User Controls to work :) I decided to take a break to try and calm myself down. At this point I knew this:

  • ViewData[“nastyAssString”] worked, it was nasty, but it worked and was really quick to implement.
  • The abstract Master Model with abstract Controller worked real nice but caused issues with strongly-typed content pages. This is obviously no good since that is one of the most powerful features of MVC!

Then it hit me, why not just have both?

The problem is not the ViewData dictionary itself, it’s the way we are accessing it, so why not extend the interface so we access it in the way we desire? Lets add some extension methods to our lab (in ViewDataMasterExtensions):

   1: public static string GetHeader(
   2:  this ViewDataDictionary viewData)
   3: {
   4:     return
   5:      viewData["Master.Header"] as string;
   6: }
   7:  
   8: public static void SetHeader(
   9:  this ViewDataDictionary viewData, string header)
  10: {
  11:     viewData["Master.Header"] = header;
  12: }

Here we are simply creating some getter/setter methods for the values we are interested in, we can then set these in the BaseController:

   1: public BaseController()
   2: {
   3:     // Set the Master Page Data
   4:     ViewData.SetHeader("Header Set in 'BaseController' via Extension Method");
   5:     ViewData.SetSubheader("I can haz master page model data?");
   6: }

And also retrieve them in the master page:

   1: <h1><%
   1: = ViewData.GetHeader() 
%></h1>
   2: <h2><%
   1: = ViewData.GetSubheader() 
%></h2>

Note the Form now also works as desired. Happy face :) Just because this is simple model data, it does not mean it has to be. It could also be really complex data that is rendered by User Controls ;)

Solution Review

  • I certainly do not think this the most elegant way of doing things, but it does work and is quick to implement.
  • I was worried about using the ViewData dictionary as the hook, but this could easily be resolved by building classes to wrap sets of data and bolt them on to build a more friendly, cleaner API to the ViewData (e.g. “ViewData.Master.Header”).
  • It would be really cool if the MVC team could come up with some way for us to have a “Master Page Model” that can easily slot in and only affect the Master Page.
  • There is no hierarchy of Models (with base classes etc.), everything is hooked up in the controller, as it should be.

Just to reiterate: I am a newbie to MVC so I could be missing something! If you feel there is a better way or have pointers on what we have, then please comment!

Tuesday, 21 April 2009

Tech Day #3 – Inversion of Control (IoC) Containers

For my third tech day I had a bit of an internal fight over whether or not I should get started with WPF, or take a look at IoC containers. As you can tell from the title, I went with IoC containers since I thought the knowledge would be more useful to me at this point.

What is an Inversion of Control (IoC) Container?

The first obvious question. Before we answer this through we should talk about some base concepts that are important to IoC. We’ll come back to this in a minute..

What are the Basic Concepts Behind IoC?

The Hollywood Principle

I first heard about this in Head First Design Patterns (I also strongly recommend grabbing the poster). In short this basically says “don’t call us, we’ll call you” – lower-level classes that perform specialised tasks lose their control, instead being called by higher-level classes. These higher-level classes provide the “hooks” for the lower-level classes to “slot in”. Lower-level classes don’t get to call the big-shot higher-level classes.

In the sample code for this post, check out the “HollywoodPrinciple” namespace, there are some simple classes in there that will demonstrate the Hollywood Principle.

Note that the actors have no influence over the director at all, they simply do as they are told. The director maintains control of the application flow by calling the Action and Cut methods, but the actual people responsible for doing the work actually make it happen.

Dependency Injection

Following on from the Hollywood Principle, the next key component is dependency injection. This is basically the declaration of a class that it needs something to do it’s job. Having applied the Hollywood Principle in the previous code, we now have a HollywoodDirector who is in charge of some Actors, but when newing up the director, this is not immediately obvious.. We could look real silly asking the director to start filming a movie if we forget to tell the actors to show up!

This is where dependency injection comes in. We make a clear statement in our API that we need something in order to be able to operate. At this point, I invite you to review the sample code in the “DependencyInjection” namespace.

See we now have a DependentHollywoodDirector? In this class there is only one small, but significant change. We have added a parameter to the constructor, asking for a List<IActor>. We are saying that the director cannot do it’s job without the actors and have completely removed the directors ability to create it’s own pool of actors (read “removed the new List<IActor>”).

Why is this useful? Simply put, it puts the client code of the director in control of how the director operates. Review the demo code and note that we have added another Actor to the mix without altering the director code.

Inversion of Control - Oh, Did You Miss It?

Yeah, it’s pretty subtle, but we have just applied inversion of control to our code. Since the client code (i.e. the “Demo” code) is now actually altering what our director has to work with. It’s important to note that it does not change how the director does his job - he will always call “Action!” and “Cut!” no matter what actors he is working with. We have also made a clear declaration of intent by placing the actor requirement in the constructor.

So, back to our original question..

What is an Inversion of Control (IoC) Container? (Redux)

An IoC container enables us to abstract away the dependency chain introduced by dependency injection.

Think about the Hollywood example we have had so far..

  • We have a director that requires actors.
  • Each actor requires a make up artist, and a stunt double.
  • Each make up artist requires a bunch of cosmetics to work with.
  • Each stunt double needs some great medical insurance.
  • The medical insurance requires financial and health information about the stunt double.

As you can see, if you have a complex object model (which can easily become the case) you could ultimately be looking at crazy code like:

   1: IActor someActor = 
   2:     new Actor(
   3:         new MakeUpArtist(
   4:             new CosmeticsCollection()),
   5:         new StuntDouble(
   6:             new HealthInformation(),
   7:             new FinancialInformation()));

.. and this is a relatively simple model. But do you want to do this for every actor/make up artist/stunt double?

IoC Containers take away this pain by allowing us to dictate to the container what the dependencies are, and how we want to react to them. When we then ask the container to give us an Actor, it will automagically create the required make up artist and stunt double, along with all the required information they need.

Sounds Complicated? Is It?

The funny thing is, the concept of IoC is pretty simple. But as with most things, they can quickly get blown out of proportion to make it also do “cool stuff”. This puts many people (including myself) off of full-blown containers such as Castle Windsor Container, Spring.NET, Autofaq and many more.

That said, I decided I should see what it is like to write a simple IoC container myself. This was intended to be nothing fancy, but simply a little utility to give us what we need.

robcthegeek’s MAC (Major-Awesome Container)

Yes, the above is all lies and propaganda. But let’s continue.

We are only looking for something simple here. Once the info to tell the container what to do has been provided, we simply then want it to new up objects for us, fulfilling their dependency chain.

Review the “MAC” namespace in the sample code.

Note we have a few classes:

  • robcthegeek – which wants to geek out, but needs coffee and a bag of chocolate peanuts.
  • BagOfChocolatePeanuts – they are yummy!
  • CupOfCoffee – all geeks are sustained by caffeine, but this coffee needs sugar!
  • TeaSpoonOfSugar – needs to go in the coffee!

So, whenever we want a robcthegeek to geek out, we need to new up all of this stuff! Let’s seen if the Major-Awesome Container™ can help!

Building the Container

Now, containers can be very fancy and do lots of reflection and the like to improve the syntax required to use them. In the interest of time, I am not going to be doing all that. This is simply to demonstrate the concept of an IoC container, if you want one with bells and whistles, then check out the container projects listed later.

So, what does the MAC need to do?
  • It needs to be able to take the required configuration from us, so it knows which classes to create for us and their related dependencies.
  • It needs to be able to give us the classes!

Right, so lets start at the top, how do we tell it how to create classes for us?

NOTE: The code in the code sample is not supposed to be anywhere near representative of production-quality code!

Setting the MAC Configuration

Basically, we need to say to the MAC “I want a type, and I want it to be created like this”. So I thought I would keep it as simple and have a method like this:

   1: public void Register<T>(Func<T> factory)

Here we simply have a generic method that takes a delegate that must return the type being registered. Can’t be much simpler than that right?

Getting Classes from the Container

Next, we need to get a type from the container, so what could be simpler than:

   1: public T Get<T>()

Bringing it Together
   1: // Create the Container and Configure.
   2: MAC container = new MAC();
   3:  
   4: container.Register(() => new CupOfCoffee(
   5:                      new TeaSpoonOfSugar()));
   6: container.Register(() => 
   7:     new robcthegeek(
   8:         new BagOfChocolatePeanuts(),
   9:         container.Get<CupOfCoffee>()));
  10:  
  11: // Now Get a "robcthegeek" from the Container..
  12: // Note here we are not needing to spin up dependencies.
  13: var rob = container.Get<robcthegeek>();
  14: rob.GeekOut();

Easy! And if you look at the sample code there is not a lot to the “MAC”.

But, as said before, this is a real simplistic example. The code for the “MAC” is far from production-ready (e.g. there is no error checking in there to make sure types are registered). Also we could perhaps infer the factory methods based on default constructors and things like that. But remember, if you want a “proper” container, then go and get one, there are plenty out there (or start a new one!).

IoC Containers Worth Using

Even though the MAC is MAJOR AWESOME in its design, there are several others that are definitely worth your attention:

In Summation

Dependency injection and inversion of control help us to write much more loosely-coupled cohesive object model. While this brings about many benefits in the design and maintainability of our application, all is not rosy. A large amount of dependencies are naturally introduced, and these must be satisfied in order to get classes created. IoC containers help reduce the pain of this by providing a one-stop shop for us to define the dependency chain and then perform this process for us each and every time we need a class.

Very useful.

I will be reviewing the “IoC Containers Worth Using” in the near future.. Stay tuned.

Monday, 6 April 2009

Tech Day #2 – jQuery

image So, it seems to have come around quickly, but I have arrived at the 2nd day of my reduced hours at work! This time around, I wanted to look at jQuery.

I am really looking to specialise and get deeper in to web development, part of this is building on my knowledge of user experience. I am a huge fan of writing software for the user – not the client, TBH, I’m not even a fan, rather a zealot. Sure, we build software on behalf of a client, but the one who gets the pleasure (or pain) of working with the software is the user. Always put yourself in their shoes.

Why jQuery?

Part of creating a better user experience is to provide a better interface. It should be responsive, aesthetically pleasing and “just work”. Javascript has become a big part of this in the web world. Since the code executes on the client side (rather than the server) there is no round-trip to the server, no page reload – it’s pretty seamless to the user.

jQuery has [pretty rapidly] become the weapon of choice for people wanting to more with javascript without having to type out lots of boilerplate code. There are other alternatives to jQuery (such as Prototype) which has their own pro’s and con’s – but that’s another tech day :)

The main reasons I decided to hit jQuery first are plain in simple:

  • It’s massively popular, there is a LOT of support out there for it in the community.
  • It’s integrated right into Visual Studio and officially supported by Microsoft.
  • I also know jQuery is fully CSS3-compliant, which will just help reinforce my CSS skills.

Let’s Get Acquainted!

Before getting in to the good stuff, I wanted to have a read of jQuery in Action to get a brief understanding of what goes on and how it works..

“Unobtrusive Javascript”

One of the first things the book hits on is the notion of “Unobtrusive Javascript”. Basically this states that if we have behavioural code added to our HTML markup, we are polluting it. This is similar to using inline styling versus CSS. The HTML should only dictate the page structure, nothing more.

This raises the question of “where the hell do I put the Javascript then?”. With CSS, we simply add a LINK element to the HEAD section of the page. But how would I create the following:

   1: <input type="button" id="button1" onclick="doStuff();" />

From:

   1: <input type="button" id="button1" />

The answer is to hook it up using javascript itself, with code similar to:

   1: document.getElementById("button1").onclick = doStuff();

So we actually implement the behaviour by executing a series of statements to hook up the behaviour to the interface. This offers the following benefits:

  • MUCH cleaner markup.
  • Behaviour can be changed at run time by simply altering what behaviour is hooked up to what elements.
  • Changes to the design (logical, not appearance) do not mean lots of find-replace operations.

NOTE: It’s important to remember to only attempt to hook up the behaviour AFTER the elements have been loaded into the DOM.

Selecting Elements to Work With

As stated before, jQuery is fully CSS3 compliant, but you may be wondering “what the hell has CSS got to do with javascript"?”. And you would be right to do so, they have nothing to do with each other. However, jQuery uses CSS3-compliant selectors to retrieve elements from the DOM.

Consider the following CSS:

   1: p a
   2: { border: solid 1px #F00; }

This CSS selects all links that are within a paragraph element and set’s a one-pixel red border around them.

In jQuery we can also select the same elements by:

   1: jQuery("p a")
   2: // or to use the alias..
   3: $("p a")

Note that the text used (“p a”) to select is exactly the same! We also used of the jQuery alias “$” for the jQuery wrapper function. It’s called a wrapper function because it actually wraps the elements returned with extra functionality. For example, jQuery commands can be called on the set like the following:

   1: $("ul li").fadeOut();

This will get the set of any list item elements within an unordered list, and then fade them out. Sweet!

Chaining

Another cool feature of jQuery is that the elements are returned from commands, so you can execute further commands on them. Consider:

   1: $("a[href^http://]").prepend(">>").addClass("extLink");

This will locate all external links (those that begin with “http://”) and then prepend the link text with “>>” as well as add the CSS class “extLink” to the elements.

jQuery and Advanced Selectors

I found this to be really cool. Let’s take the following from the previous code snippet:

   1: $("ul li:nth-child(3)")

This CSS selector is actually a CSS3 selector which is not supported by all major browsers at this time. What is cool is that jQuery is actually doing the heavy-lifting on the element selection. Which means that the above will allow us to apply styling and behaviour to elements that are not actually supported by the browser (the above works in IE7 and Firefox* which do not actually support the selector). So if you need to apply some cool CSS to only the third list item in an unordered list, use the following:

   1: $("ul li:nth-child(3)").addClass("coolCssClass");

* Yes, I wanted to pick on Firefox as well as IE :P

“Document Ready”

Recall earlier that I said the elements must be loaded into the DOM before we start to play with manipulate them? How do we ensure that the document has completed loading? Traditionally, you may use something like:

   1: document.onload = doFunkyStuff();

While this works, there is a major problem. The “onload” event is only fired after ALL the elements have been loaded. This includes all external images and resources, everything. This is likely to be really undesirable behaviour. Don’t fear, jQuery to the rescue! jQuery provides us with the ability to hook up methods to an event that occurs when the DOM structure has been created, but resources may still be loading.

   1: $(document).ready = doFunkyStuff();
   2: // or the shorthand..
   3: $(doFunkyStuff());

Simply passing the methods into jQuery will cause them to be executed once the DOM is ready (they are executed FIFO). Handy!

To the Code!

I wanted to keep things as simple and focused as possible, so here is my setup:

  • I downloaded jQuery 1.3.2 (this is the non-minified version so I could have a look at what the code was doing myself).
  • Using plain old HTML, no Visual Studio, no ASP.NET, no Intellisense, no IIS, just N++ and a browser – let’s get old-skool baby!
  • I created a template HTML file that will serve as the base for all the little “labs”. Not much here, just a few links and little bit of styling.

Download the lab files and follow along! 

Lab 01 – Adding Some Style!

Let’s start simple, I want to apply some CSS styling to some elements on the page. I have opted to add a little style to all the external links on the pages.

This will require the use of the CSS3 attribute selector to figure out if the link is external. We are going to assume that all external links are prefixed with “http://”. Below is the script used:

   1: $(setExternalStyles);
   2:  
   3: function setExternalStyles()
   4: {
   5:     $("a[href^=http://]").addClass("extLink");
   6: }

And the CSS style:

   1: .extLink
   2: {
   3:     background-image: url(../img/extLink.jpg);
   4:     background-repeat: no-repeat;
   5:     padding-left: 13px;
   6: }

Remember, what is really cool is that we are using a CSS3 selector, and getting the right results in all browsers. This is taken from IE7:image

Lab 02 – Adding Some [Attribute] Value

A natural extension to lab 01, let’s take it one step further and ensure all of our external links are opened in a new window.

   1: $("a[href^=http://]").addClass("extLink").attr("target", "_blank");

Here we simply add another method to the chain to set the “target” attribute to “_blank”.

Note there is no change at all to the markup, and we have totally stripped away the behaviour of the markup elements.

Lab 03 – All Your Text Are Belong to ME!

Keeping the flow of the link list going, let’s take it one step further. I often get annoyed when links are presented with the text of the link itself for example: http://google.co.uk, why not just Google? In this lab we see if jQuery can help us clean up our users screen..

This was an interesting exercise, since I admit my javascript is a bit shaky, so if you have any suggestions on how I can improve the code, then please comment and let me know!

Here is the javascript to make lab 03 happen:

   1: $(setExternalStyles);
   2: $(replaceWebUrlElements);
   3:  
   4: function setExternalStyles()
   5: {
   6:     $("a[href^=http://]").addClass("extLink").attr("target", "_blank");
   7: }
   8:  
   9: function replaceWebUrlElements()
  10: {
  11:     $("#content a[href^=http://]").each( function(idx)
  12:     {
  13:         var html = this.innerHTML;
  14:         // scrub the http:// prefix.
  15:         var rep = html.replace("http://", "");
  16:         
  17:         // check for & scrub the www.
  18:         if (rep.substr(0, 4).toLowerCase() == "www.")
  19:             rep = rep.slice(4, rep.length);
  20:         
  21:         this.innerHTML = removeDotSuffix(rep);
  22:     });
  23:     
  24:     function removeDotSuffix(url)
  25:     {
  26:         var suffixes = new Array(".com", ".co.uk", ".org"); // this can go on forever.
  27:         
  28:         for (idx in suffixes)
  29:         {
  30:             var currSuffix = suffixes[idx];
  31:             
  32:             if (url.substr(url.length - currSuffix.length, currSuffix.length) == currSuffix)
  33:             {
  34:                 var rtn = url.slice(0, url.length - currSuffix.length);
  35:                 return rtn;
  36:             }
  37:         }
  38:         return url;
  39:     }
  40: }

As you can see, we are extending the original functionality from lab 02 by simply adding another method to clean the text. We then took the cleaned text and set the innerText of the link within an iterator nicely provided by jQuery.

I also refined the selector for the “url cleaner” to the main content div so it does not affect any other links on the site (e.g. in the footer).

Lab 04 – Do Something Sexy!

Often a real driving factor for people wanting to get in to jQuery is it’s support for easily creating some pretty slick effects on page elements. In this lab we look at performing some effects on page elements following a user action.

I decided I wanted some links, that when clicked would fade in an “about” box containing more information about the information clicked. This should then be able to be “toggled” (i.e. if showing, then hide it and vice versa).

Here is the script I used:

   1: // taken from: http://bit.ly/bMpZc
   2: jQuery.fn.fadeToggle = function(speed, easing, callback) {
   3:     return this.animate({opacity: 'toggle'}, speed, easing, callback);
   4: }
   5:  
   6: $(setup);
   7:  
   8: function setup()
   9: {
  10:     $("#aboutList li span").hide();
  11:     $("#aboutList li a").click(function ()
  12:     {
  13:         $(this).siblings("span").fadeToggle("slow");
  14:     });
  15: };

Nothing majorly fancy going on here. I had to Google to see how to toggle with the fade effects (link in the code). Once I had that, I then needed to figure out how to get a reference to the span element within the list item. Having checked the jQuery documentation, I came across the siblings traversal method, which made it easy.

I really liked how this worked out, the fact that there are no ID’s (other than the reference to the unordered list – which isn’t really required, it just makes the route easier) kinda blew me away. The fact that the this keyword is always in context makes things a lot easier.

For example, in the lab when adding our “click” handler, the “this” referred to the link element being clicked. I then knew that the span elements were siblings to these elements, so I don’t need an ID to find them. This is exactly why document structure is important, and not the ID’s attached to them! Behaviour can be implicitly defined based on where it is within the structure!

Lab 05 – Do Something For Me!

image In this lab I thought it would be interesting to play with the Ajax functionality provided by jQuery. Since I have never worked with JSON, and jQuery has a handy method for it, I thought I would check it out.

Twitter has a JSON API method for their search, so this seemed an ideal candidate to quickly hook in to. The code below was all it took to get the top 15 search results for “robcthegeek” from Twitter and display them on the page:

   1: $(getTwitterResults);
   2:  
   3: function getTwitterResults()
   4: {
   5:     $.getJSON("http://search.twitter.com/search.json?callback=?&q=robcthegeek",
   6:         function (json) {
   7:             $(json.results).each( function() {
   8:                     $("#searchList").append("<li>" + this.text + "</li>");
   9:                 });
  10:             });
  11: };    

How freaking awesome is that?!

To Close…

I think I will knock it on the head there with the labs for now. I have taken a (albeit broad) look at the basics of jQuery and tinkered about with them. I intent to get my website up and running real soon, so I will play with it a lot more during the development of that.

Overall, I have really enjoyed today. I was expecting it to be quite a painful process getting in to jQuery (and working more with Javascript) but that has not been the case. jQuery obviously has a well-thought-out API. I feel like it is doing enough of the “right stuff”, rather than try to do EVERYTHING and just end up with a leaky abstraction. The documentation is fantastic and quickly got me up and running when I wasn’t sure where to tread next. Even if the documentation isn’t sufficient (such as with the toggle fade in lab 04) I am pretty sure a Google will find you answers quickly.

It has also been refreshing to drop the IDE and get back to basics with notepad. I have found it actually helps you focus on either the script or the markup, rather than worrying about databinding and what classes go where etc. I am thinking I should perhaps do this more often, especially when it comes to me planning out designs etc (e.g. get the structure right, then worry about making it dynamic).

On the whole, a great day! If you have any suggestions or comments on ANY of the above, then please do comment! All input is gratefully received!