Respond.js and My Bewildered Brain

This morning at work, I’ve been experimenting with Respond.js, a tool to adapt older browsers to support media queries. After a little initial success, I started to notice that IE8- are applying styles I’ve intended for mobile to desktop browsers.

I puzzled a while and then read this on the Respond.js GitHub page:

Craft your CSS with min/max-width media queries to adapt your layout from mobile (first) all the way up to desktop.

In my limited experience with media queries — and I believe as I learned from the Bible…er…Responsive Web Design — I have taken an existing desktop design and media-queried it.  This means that I have defined styles in my style sheet, like:

div#container {
    background-color: #ffffff;
    color: green;
    width: 85%;
}
@media only screen and (min-device-width: 320px) and (max-device-width: 480px) {
    div#container {
        width: 100%;
    }
}

That way I apply the same background color and font color to all displays and then just adjust the width for the browser targeted in the media query.  Now I see that to use Respond.js, I need to approach it from the opposite angle:

@media only screen and (min-device-width: 320px) and (max-device-width: 480px) {
    div#container {
        background-color: #ffffff;
        color: green;
        width: 100%;
    }
}
@media only screen and (min-width: 800px) {
    div#container {
        width: 85%;
    }
}

Okay, I see how this is in keeping with the spirit of responsive/progressive design, but it sure makes renovating an existing design 0% fun.  Also, I feel like I’ll be left with stylesheets that are mostly media queries.

Just when you think you understand something, you realize you hadn’t even begun to see the ice at the surface.

Write iCalendar File with C#

Just a little neat thing and how I did it.  It’s probably not the best or most elegant way to get there, but here it is anyway.

iCalendar is a special text file that holds calendar event information. It has the extension .ics and can be read by Microsoft Outlook, Apple iCal, Google Calendar, and probably other calendar-consuming applications.  The following example, however, has only been tested on those three applications.

At work, we have a calendar on our home page which is fed from a SQL Server database. One day I thought, “Wouldn’t it be cool if a user could download the entire calendar for the month to a computer and open it with a calendar application? Then the user can have every Frederick County meeting popping up on his iPhone. How cool would that be?”

Well, the ultimate answer might be: “not very cool.”  I discovered that when I accidentally added ten bazillion meetings to my personal calendar while testing this.  I still get an occasional reminder about a Board of Zoning Appeals meeting.

Anyway, let’s assume the answer is, “very cool!”  The process is actually pretty simple (after one spends a few weeks in his scant free time at work learning how iCalendar works and then tweaking the code).  Basically, since iCalendar is a text file, I figured I could skip third-party and possibly non-free ASP.NET iCalendar tools and painful changes to my database by simply writing my own iCalendar file.

First, I get the events published in the last 30 days by querying the events table and including WHERE [calPubDate] >= CURRENT_TIMESTAMP – 30 in the query.  That gets loaded in a DataTable called xmlTemp.  Then, I simply write the contents of the table to the iCalendar file like this:

// Create new StreamWriter to write iCalendar file.
StreamWriter sw = new StreamWriter(Server.MapPath("/fredcocal.ics"), false);
// Write the opening line of iCalendar.
sw.WriteLine("BEGIN:VCALENDAR");
// Write the version (2 required for OS X iCal).
sw.WriteLine("VERSION:2.0");
// Loop through rows in data source to write each event.
foreach (DataRow row in xmlTemp.Rows)
{
    // Get the start datetime for the event.
    DateTime dtStart = Convert.ToDateTime(row["calDateStart"]);
    // Add hours to get it to UTC.
    dtStart = dtStart.AddHours(5);
    // Get the end datetime for the event.
    DateTime dtEnd = Convert.ToDateTime(row["calDateEnd"]);
    // Add hours to get it to UTC.
    dtEnd = dtEnd.AddHours(5);
    // Create string to format start time properly.
    string strStart = dtStart.ToString("yyyyMMdd'T'HHmmss");
    // Create string to format end time properly.
    string strEnd = dtEnd.ToString("yyyyMMdd'T'HHmmss");
    // Create a string for the event title.
    string strSummary = (string)row["calTitle"];
    // Create a string for the event description.
    string strDesctiption = (string)row["calDesc"];
    // Write the event start.
    sw.WriteLine("BEGIN:VEVENT");
    // Write the event summary.
    sw.WriteLine("SUMMARY:" + strSummary);
    // Write the event description. (URL added for display in description.)
    sw.WriteLine("DESCRIPTION:" + strDesctiption + " URL: " + (string)row["calXmlLink"]);
    // Write the start time of the event. The Z is for UTC.
    sw.WriteLine("DTSTART:" + strStart + "Z");
    // Write the end time of the event. The Z is for UTC.
    sw.WriteLine("DTEND:" + strEnd + "Z");
    // Write the URL of the event.
    sw.WriteLine("URL:" + (string)row["calXmlLink"]);
    // Write the event end.
    sw.WriteLine("END:VEVENT");
}
// Write the end line of iCalendar.
sw.WriteLine("END:VCALENDAR");
// Close the StreamWriter.
sw.Close();

 

You may notice that I just request the URL as (string)row["calXmlLink"] without a variable like the other parts.  That’s just because I added the URL as an afterthought.  Still works.

The result is an iCalendar file that can be read in Outlook, iCal, and Google Calendar.

Things to note along the way: Apple iCal requires iCalendar files to be version 2 and have no blank lines.  My first attempts at this created an iCalendar file that had blank lines between the events to help me when I had to look at the file, but I killed those so iCal could consume the events.  Also, the datetime format of iCalendar gave me some trouble because I had not been very intelligent about my storage of the times and dates in the database; therefore, I have to add 5 hours to each datetime to get it to UTC and then add a Z at the end of each DTSTART and DTEND element so it looks like UTC.  Not a big deal, but I’ll have to revisit my application in a few months to change AddHours(5) to AddHours(4).

Want to read more about time in a web page? Check out Microformat: hCalendar in an ASP.NET page.

Microformat: hCalendar in a .NET Page

A few months ago, I read Adaptive Web Design by Aaron Gustafson. If you have anything to do with making web pages, read this book.  And while you’re at it, also read the entire A Book Apart series.  Excuse me while I wipe all that brown off my nose.

Anyway, among the 48 tons of awesome knowledge in Adaptive Web Design, Aaron introduced me to microformats. These are cool formats based on existing usage patterns that allow web designers and developers to include extra information in a page’s markup. In keeping with the spirit of responsive design, these extra bits of information enhance the experience for those who can use them and have no impact on those who can’t.

There are many kinds of microformats, but the one I was immediately interested in is called hCalendar.  The hCalendar format basically embeds a calendar event into a web page with special markup.  If a user has something to read hCalendar markup, like a plugin for Firefox or Chrome, that user can download the event, add the event to a calendar, or do anything else the app allows.  Because we have a calendar on our home page, I figured it would be cool to add hCalendar code to our existing calendar items.  With a very brief re-work of the existing calendar items, I was able to include hCalendar functionality:

<asp:Label ID="lblOpenAnchor" runat="server" class="vevent">
    <a id="calendarLink" runat="server" href='<%# DataBinder.Eval(Container.DataItem, "calLink") %>' target='<%# DataBinder.Eval(Container.DataItem, "calTarget") %>'><%# ((Convert.ToDateTime(Eval("calDateStart")) == DateTime.Today) ? "Today" : Convert.ToDateTime(Eval("calDateStart")).ToString("MMMM d"))%>: <span class="summary"><%# DataBinder.Eval(Container.DataItem, "calTitle").ToString().Contains('&') ? DataBinder.Eval(Container.DataItem, "calTitle").ToString().Substring(0, DataBinder.Eval(Container.DataItem, "calTitle").ToString().LastIndexOf('&')) : DataBinder.Eval(Container.DataItem, "calTitle").ToString() %></span></a>
    <span class="dtstart" title='<%# Convert.ToDateTime(Eval("calDateStart")).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'-05:00'") %>'></span>
    <span class="dtend" title='<%# Convert.ToDateTime(Eval("calDateEnd")).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'-05:00'") %>'></span>
</asp:Label>

 

That server-side code is part of an ASP.NET Repeater which is bound to calendar items in a data source. That repeater results in the following example markup in the browser:

<span id="rptCalendar_lblOpenAnchor_6" class="vevent">
    <a href="http://www.co.frederick.va.us/board_of_supervisors/" id="rptCalendar_calendarLink_6" target="_self">January 25: <span class="summary">Board of Supervisors meeting</span></a>
    <span class="dtstart" title='2012-01-25T19:15:00-05:00'></span>
    <span class="dtend" title='2012-01-25T21:00:00-05:00'></span>
</span>

 

The class=”vevent” attribute tells the microformat parser that this is some hCalendar info.  Then we have a summary and some start and end times.  Here’s what it looks like in Chrome with the microformat parser:

Many people who use hCalendar actually use the <abbr> element for the times, but in HTML5, we have the <time> element. Unfortunately, at the time I was creating this, the CSS3 Working Group was unsure of supporting the <time> element moving forward.  I did not want to use the <abbr> element for times because it just didn’t seem semantically appropriate (not that I never abuse semantics), so I opted to just mark a span up as time.  That worked fine, made me feel good, and didn’t carry over any special formatting or functionality that browsers might apply to <abbr> in our CSS non-reset website.

Neat stuff.  Now, if a user is extremely interested in that Lake Holiday Dam Working Group meeting, he can easily add it to his calendar.  If a user doesn’t have something to parse microformats, he doesn’t even know he’s missing anything.  That, I believe, is progressive enhancement.

Want to read more about time in a web page? Check out Write iCalendar file with C#.

New Music Report

Thanks to the RIP Morbid Angel Facebook user, I discovered Cruciamentum. While seeking some Cruciamentum, I discovered Balfor and their extremely awesome Barbaric Blood album. Well done, internetz.

It is nice to get those Manowar and Vader albums back again.  Also, I don’t care what my “true metal” or whatever friends say: I really enjoy Shinedown.

Balfor – Barbaric Blood
12 Stones – The Only Easy Day Was Yesterday
Manowar – Fighting the World
Vader – De Profundis
Vader – The Ultimate Incantation
Cruciamentum – Convocation of Crawling Chaos
Cruciamentum – Engulfed in Desolation
Shinedown – “Bully” single (on iTunes)

Great Topics: Entropy and My Wife

This is just a passing thought about physics from a guy who isn’t well-educated about it. I posed this to my father and wife tonight:

If entropy is disorder, “hot” things are more entropic than “cold” things, and thermodynamics says that entropy increases over time, why do things get colder instead of hotter? Shouldn’t increasing entropy cause temperature to rise?

Then, since she is brilliant, my wife suggested:

Well, what happens as things get colder?

Then I concluded:

As they get colder, they lose energy; therefore, thermodynamics is supported: the loss of energy is an increase in entropy. That may result in a colder material, but the entropy nonetheless has increased.

It may or may not be true that there is a great woman behind every great man, but there certainly is a great woman behind this man.

The Hobbit and a Responsive Web Design Proof of Concept

Note: Everything I do around here is subject to catastrophic revision. I’ll probably try to improve this Hobbit countdown frequently for a few days. If something is seriously wrong with it, that’s probably what’s going on. Anyway…

It is extremely cruel to release the trailer for The Hobbit one year before the movie is in theaters. I foresee an agonizing year of glacial time motion as I anticipate what will surely be the first move I’ve cared to see multiple times in the theater since The Lion, the Witch, and The Wardrobe and only the second since Star Trek VI: The Undiscovered Country.

Now that you have incontrovertible evidence of my nerdiness, let’s take a look at a responsive web page: http://www.jcoulson.com/hobbit/count.html. It clearly isn’t perfect, but it’s responsive nonetheless and will serve as an interesting proof of concept at work when people ask, “But what can you do with progressive enhancement?” (A far better example would be http://www.westminster-abbey.org, but there are no Middle Earth stories available there.)

The content for the page is pretty simple: a div into which a jQuery plugin called jQuery Countdown loads a countdown timer, a div holding an a that points to the movie trailer, and a p with an img of the movie poster. That’s pretty much where it was until I started playing around last night.

Then I got a little wild. Just a little. Brief overview:

  • The movie poster is loaded a background image for most users.
  • A jQuery plugin called Backstretch stretches the background image to fit the display since the CSS3 background-size property is not supported in browsers yet.
  • The background stretches nicely, but many mobile users and users of much larger displays might find the image distorted. So, two media queries hide the image put in place by Backstretch and replace it with the static image in the paragraph.
  • Media queries also resize and reposition text and elements on the page for different displays from small mobile screens up to much larger displays.
  • CSS @font-face rules load that non-standard font. The font came from Font Squirrel.

It probably isn’t a perfect example of responsive design, but it shows the concept. I’m sure if I’d thought it out more clearly, it would work better and my CSS would be cleaner. Nonetheless, the same content is manipulated into different places and sizes to be useful to users of many different devices. I tested the page on my big desk monitors, on resolutions higher than what I own with ViewLike.us, and on an iPad and iPhone with Safari in both portrait and landscape modes.

New Music Report

Thanks to Goodwill and Ear Food for very cheap and awesome used stuff.

Joseph Haydn – Symphonies 88-92
Saint-Saëns/Britten – Christmas Oratorio/A Ceremony of Carols
Richard Wagner – Tannhäuser

See that Haydn CD? Look at the title. This guy wrote 108 symphonies and a whole lot of other stuff. Incredible. That’s prolific. So far I’ve created like nine websites and not even written 1/8 as much music as Haydn did. I’m 33. Time to get cracking.

New Music Report

This covers a few weeks and includes the things I decided to keep from my Blood and Ink boxes.

Saints Never Surrender – Hope for the Best, Prepare for the Worst
Skylines – Identity
Dynasty – Truer Living with a Youthful Vengeance
Ten-33 – Emergency! Emergency!
Leper Lord – Altar of Embers
Vader – Necropolis
Nourish the Flame – Trial into Triumph
Edward Elgar – Cello Concerto/Sea Pictures