Wednesday, 30 June 2010

This is ridiculous!

image

Ever heard of atomic operations? If one bit fails, the entire thing should fail – don’t take my money and then not book my tickets!!! If you MAY have taken my money then you’d better damn well get in touch with ME, especially as it’s 10:01pm and your line’s are closed. Ridiculous!!!

Tuesday, 29 June 2010

Overriding the style of a jQuery UI datepicker

Recently, in my spare time, I’ve been working on a simple booking system for a friend of mine. I had the need to present a date selector using jQuery UI’s date picker, but I wanted to change the default behaviour as follows;

  • Dates in the past can’t be selected and must be stylised
  • Dates in the future can be selected, but the calendar should highlight any dates that are not available
  • I don’t want to go hunting and changing my jQuery UI theme styles, nor do I want to modify any jQuery UI code

The starting point – vanilla datepicker

Adding the following code;

$("#startDate").datepicker({
    numberOfMonths: 3,
    showButtonPanel: true,
    dateFormat: 'dd MM yy',
});

Provided the following default behaviour;

image

Disabling dates in the past and dates that have bookings already

So this part is pretty simple, the component provides us with two hooks of note – onChangeMonthYear which is fired when the user navigates the calendar between months or years etc (but not on first display) and the second – beforeShowDay, which is called before an actual day is rendered into the control and allows you to specify whether the date is available, any extra css to apply and a tooltip to show.

I could use the onChangeMonthYear event to load my known events via a JSON call and then check the variables in the beforeShowDay event, but to be honest I’m going to only be interested in future bookings and there aren’t going to be a massive volume. As such, I can afford to load all the events using a single ajax call during page start up and then interrogate the result in beforeShowDay.

So, my code to implement the datepicker now looks like this;

$("#startDate").datepicker({
        numberOfMonths : 3,
        showButtonPanel : true,
        dateFormat : 'dd MM yy',
        beforeShowDay : calendarDayShow
    });

with the following function;

  1. function calendarDayShow(targetDate)
  2. {
  3.     var availableResult = [true, '', ''];
  4.     var bookedResult = [false, '', ''];
  5.  
  6.     var now = new Date();
  7.     if (targetDate < now) return bookedResult;
  8.  
  9.     var targetYear = targetDate.getFullYear();
  10.     var targetMonth = targetDate.getMonth();
  11.     var targetDay = targetDate.getDate();
  12.     if (typeof (availability[targetYear]) == "undefined") return availableResult;
  13.     if (typeof (availability[targetYear][targetMonth]) == "undefined") return availableResult;
  14.     if (typeof (availability[targetYear][targetMonth][targetDay]) == "undefined") return availableResult;
  15.     return bookedResult;
  16. }

The component expects this function to return an array in the format of [<<availability>>, <<css>>, <<tooltip>>]. It’s worth noting that my availability data is stored as a JSON object in this hierarchy; (If there is an entry, that date is booked).

  • YYYY
    • MM
    • MM
      • DD = true
      • DD = true
  • eg: 2010
    • 6
      • 15 = true
      • 16 = true

So, on the above code, lines 3+4 are defining the available and booked responses. Line 6-7 checks if the date being rendered is in the past, and if it is, it returns a booked result to prevent it from being selected. This now results in the following;

image

Notice that 1st Aug and 12 July are booked in this example.

Making it look how I want it.

This is all well and good, but I want past dates to appear as disabled and booked dates to appear with a red X through them, like this end result:

image

I’m pretty sure you already know the answer – the beforeShowDay event expects us to pass back availability, and extra CSS classes to apply plus any tooltip we want. So we change our function thus;

function calendarDayShow(targetDate)
{
    var availableResult = [true, '', ''];
    var bookedResult = [false, 'bookedDayCalendar', 'Booked'];

    var now = new Date();
    if (targetDate < now) return [false, 'pastDayCalendar', 'Can\'t make bookings in the past!'];

    var targetYear = targetDate.getFullYear();
    var targetMonth = targetDate.getMonth();
    var targetDay = targetDate.getDate();
    if (typeof (availability[targetYear]) == "undefined") return availableResult;
    if (typeof (availability[targetYear][targetMonth]) == "undefined") return availableResult;
    if (typeof (availability[targetYear][targetMonth][targetDay]) == "undefined") return availableResult;
    return bookedResult;
}

So we’re now returning the extra CSS. We define this extra CSS is our site’s stylesheet;

/* Overides for jquery UI */
.bookedDayCalendar { opacity: 1; }
.bookedDayCalendar span
{
    background-color: Black;
    background-position: center center;
    background-repeat: no-repeat;
    background-image: url(booked.png);
    color: #aaa;
    border: none;
}
.pastDayCalendar { opactiy: 0.85; }
.pastDayCalendar span
{
    background-color: Black;
    background-image: none;
    text-decoration: line-through;
}

And voila, we get….

image

hmmm – not quite the desired result! The problem here is many of the styles are inherited from jquery UI, our reset.css and so on, and some of those styles are taking precedence over our new styles. As we are confident we want these attributes on this particular class, we can ensure they are applied with preference by adding the !important moniker to them in CSS;

.bookedDayCalendar { opacity: 1 !important; }
.bookedDayCalendar span
{
    background-color: Black !important;
    background-position: center center !important;
    background-repeat: no-repeat !important;
    background-image: url(booked.png) !important;
    color: #aaa !important;
    border: none !important;
}
.pastDayCalendar { opactiy: 0.85 !important; }
.pastDayCalendar span
{
    background-color: Black !important;
    background-image: none !important;
    text-decoration: line-through !important;
}

And we get the desired result.

image

Addendum;

Of course, you’ll want to use filter:Alpha(Opacity=…. for internet explorer;

.bookedDayCalendar { opacity: 1 !important; filter:Alpha(Opacity=100) !important; }
.bookedDayCalendar span
{
    background-color: Black !important;
    background-position: center center !important;
    background-repeat: no-repeat !important;
    background-image: url(booked.png) !important;
    color: #aaa !important;
    border: none !important;
}
.pastDayCalendar { opactiy: 0.85 !important; filter:Alpha(Opacity=85) !important; }
.pastDayCalendar span
{
    background-color: Black !important;
    background-image: none !important;
    text-decoration: line-through !important;
}

Monday, 28 June 2010

6 week sprints? You’re not doing SCRUM!

I come across this quite a lot, if you’re doing more than 30 day sprints, you’re doing scrum all wrong. Whilst I agree with the sentiment of this, there are some projects where a longer sprint cycle can be beneficial – it all depends on your team structure and the work being delivered.

To set the background, for my current project, my dev team consists of;

  • 1 x architect (me)
  • 1 x onshore architect / team lead
  • 2 x onshore developers
  • 2 x offshore developers
  • 1 x sharepoint architect

We’re implementing a reasonably large custom built system for our client and each piece of work is reasonably lengthy, with each epic consisting of complex UI along with substantial work to implement a workflow spine process, which would then be supported by several common sub-processes (with complimentary UIs).

Obviously we break out the sub-processes into their own backlog items, and then break the epics down into use-cases (formal stories) that could be implemented in each iteration, but we found that with 2-4 week iterations, it wasn’t possible to cut it any other way than to deliver demonstrable product every other iteration. Literally at the end of iteration A, we would be in an unfinished, unusable state, whilst half way through iteration B, we would finish that piece of work and start the next.

The reason for this is we would implement 2 or 3 of the main use cases per iteration, essentially having multiple concurrent work streams. Wrong? not in this case.

Many would argue that this was the wrong way to go about it, that we should have concentrated the entire effort in the sprint to one use case in order to complete it within the 4 week sprint, but I argue differently. Each use case is quite narrowly focussed, making it difficult for more than 2 people to work on the same use case at the same time. As such, Brookes Law applies. Too many chef’s spoil the broth – we’d have developers standing on each others toes left and right, so can’t add more resource to the use case implementation and the implementation of that one piece of work is too substantial to be delivered in a a 2-4 week iteration.

So, we broke the project down into 6 week sprints. More regimented scrum masters would argue that we aren’t doing scrum as a result of this decision, but I argue that such a comment is ridiculous. We’re still adhering to the very principles of scrum – we’re working from a backlog, we plan sprints into a sprint backlog, we deliver burn downs, we hold daily scrum meetings, we have a scrum master, a product owner, cross functional teams, regular demo’s to the business, and retrospectives – the only discernable difference is another 2 weeks on the sprint length to pragmatically cope with implementation of complex, atomic, use cases.

We’ve been running this way for 12 months now, and the results have been great. Open, honest, transparency between the project team and the business, and just as importantly, we delivered a month early. We’ve now rolled into another 6-8 months worth of work on the project and will be continuing to use this methodology.

Thursday, 24 June 2010

Display issues with the new editor in VS2010

I’m having major issues with the new editor in VS2010. The source window corrupts so often that it’s sometimes un-usable. This morning for instance, I’m opening .JS files and am getting the following corruption;

image

In addition if I have two files open, and I CTRL-TAB to switch between them, the display doesn’t refresh, so it appears that file 2 has the same source as file 1. I have the latest display drivers etc, and my laptop is a 6Gb Lenovo W500, so performance shouldn’t really be an issue.

The only way I’ve been able to resolve this is by zooming the editor in and back out again to force it to redraw it’s contents, but other than that, this is just a rant… I have no real solution, sorry.