Book Review: HTML5 for Web Designers

Bookmark and Share
As developers we're constantly tasked with keeping up with coding techniques, learning new technologies, and sorting out the "wow, that's awesome" from the "not actually useful because of IE6, etc". With HTML5 being the latest game-changing industry buzzword we're once again forced to dig through all the clutter. Thankfully, Jeremy Keith has done the digging for us.

I blogged about Jeremy's DOM Scripting book a couple of years ago and when I read that book I thought that he'd done the seemingly impossible. He took a convoluted and confusing subject and making it simple and accessible.  With this new book, Jeremy has done the same for HTML5.

There's no shortage of information on HTML5 (a Google search currently showings over 8 million hits).  What there is a shortage of, is practical information... How (and when) should we actually start using this?

HTML5 for Web Designers is short at only 85 pages and that's a good thing.  It's not an in-depth analysis of the specifications.  It's a quick "here's what you need to know" guidebook for developers to hit the ground running. 

All of the requisite topics are covered:

  • web forms
  • canvas
  • multimedia
  • new / updated tags
  • new structural elements
  • accessibility and ARIA
The book also details how to use all of the above with a "progressive enhancement" approach so you can start using new features but still provide fallback options for older browsers.

If you're a developer and looking to stay on top of your game, consider this a must-read.

Buy a copy from the Book Apart website.

Internet Explorer 9 'Platform Preview'

Bookmark and Share
It's been ages since I've written a blog post so I thought I'd jump back into the blogging world with a quick post about IE9. Microsoft's MIX10 conference is happening right now in Las Vegas and while I'm not there (sadly) I've been following some of the news.

Microsoft has released what they're calling a "platform preview" of Internet Explorer 9.  While it's far from being a completed browser, it does showcase some of the new features.  What's most notable about this is that Microsoft has finally seen the light and started to embrace web standards.  From HTML5 to CSS3 to a re-written JavaScript engine which promises better performance for web apps, IE9 seems to be the long-awaited step in the right direction for the world's most prevalent browser.

It's still a long ways off but Microsoft seems to finally be headed down the path towards standards compliance, which should ultimately mean less headaches for developers. Everyone keep their fingers crossed.

You can download this preview version and play with the current demos at http://ie.microsoft.com/testdrive/

Sitefinity Add to Calendar Control for Events Module

Bookmark and Share

Sitefinity CMS recently opened a Marketplace section of their website where community members can contribute various resources such as controls, modules, or themes. Since I've been using Sitefinity a lot lately I thought I'd submit a control that I wrote for one of my latest projects.

Sitefinity has a great built-in Events module that you can use to create and display an events calendar.  It has a lot of features already but I thought it could use a nice "Add to Calendar" feature which would allow you to add a specific event to your Outlook, iCal, or Google Calendar based on the date and location information entered for the event.  The control / handler I've created will do just that. Here's how you can download and setup this feature for your own web site.

Start by downloading the files.

Inside the zip you'll find the following:

A UserControls/AddToCalendar folder. This folder has the user control itself as well as the images and CSS file for it. If you need to adjust the look of the control you can do that by modifying these files. The user control itself also contains the code to create the proper link to Google Calendar. The iCal and Outlook links pass the event GUID to an httpHandler.

An add-to-calendar.ashx file. This is the httpHandler file that will take an event GUID, retrieve the necessary information, and output it into the proper .ICS format. You should upload this file into your web site root folder.

In order for the control to show up on your site, you'll need to add it into the events control template. Sitefinity has built-in templates for all of it's modules but you can override them with your own. The easiest way is to modify the existing event template. You can download a zip file of all these templates from your Sitefinity client account. The file containing the template for the event details page is ~/Sitefinity/ControlTemplates/Events/ContentViewSingleItemView.ascx. Insert the AddToCalendar user control wherever you like in this template just like any standard ASP.NET user control.

Once you've modified the template, you'll need to tell Sitefinity to use it. The easiest way is just to edit the advanced properties of the EventsView control and change the SingleItemTemplatePath property to the control you modified above. See this Knowledge Base article for more on how to map embedded controls to custom templates.

That's it. You now have an elegant way of letting users quickly add your events to their calendars.

Right Aligned CSS Background Images / IE Word Wrap Bug

Bookmark and Share

I recently built a design that called for various navigation elements to have bullets aligned to the right of each link. It seemed simple enough but turned out to be harder than I'd imagined. I started with the following CSS:

ul.bulletsOnRight { padding: 0 0 10px 0; list-style-type: none; }
	ul.bulletsOnRight li { padding: 0 0 6px 10px; background-image: none; }
		ul.bulletsOnRight li a { color: blue; text-decoration: none; padding: 0 10px 0 0; background: url(images/bullet.gif) 100% 50% no-repeat; }

This code works in most situations except for one major one. In Internet Explorer, when an item wrapped to more than one line, the bullet shows up in the wrong place, or sometimes not at all. The image below shows what was happening.

Bullet Demo

It would appear that IE doesn't know how to handle the background-position when the element wraps to multiple lines. The easy way to fix it is to apply the bullet to the last WORD in the element instead of the element itself. We can do this by wrapping the word in a span tag like so:

  • Test bullet that is long enough to wrap to two lines
  • We then move the background image and associated right padding to the span element.

    ul.bulletsOnRight li a { text-decoration: none; color: blue; }
    	 ul.bulletsOnRight li a span { padding: 0 10px 0 0; background: url(images/bullet.gif) 100% 50% no-repeat; display: inline-block; }
    

    Note that the display: inline-block; element is needed to trigger hasLayout in IE6.

    Problem solved... sort of. This technique works great, but it does require you to add an extra element to each item in your navigation which could be problematic for large sites or sites that are managed via a CMS. So let's remove that span tag and add it in when the page loads via a bit of jQuery.

    	$(document).ready(function() {
    		$("ul.bulletsOnRight li a").each(function (i) {
    			// Get the text of each link and trim any whitespace
    			var contents = jQuery.trim($(this).html());
    			// Split into an array
    			var a = contents.split(/\s/);
    			// Wrap the last word in a span tag
    			a[a.length - 1] = "" + a[a.length - 1] + "";
    			// Join the array back together and update the html text of the link
    			$(this).html(a.join(" "));
    		});
    	});
    

    This is a great example of using JavaScript for progressive enhancement of a page. While most users will see our list with bullets as intended, those without JavaScript will still see an easily-usable list so little is lost if the JavaScript is absent.

    See a demo of this code in action.

    Binding an ASP.NET Repeater to Delicious (RSS) and Twitter (Atom) Feeds

    Bookmark and Share

    I recently had a client who wanted to pull in and display some Twitter and Delicious feeds on their web site. While I'd never done this before, it turns out that it's relatively simple to do by binding an ASP.NET Repeater control to the actual XML feed itself. I thought I'd share the code in case anyone else needs to do the same thing.

    We start by creating our repeater objects, one for Twitter and one for Delicious. Since the feeds are different, and because Twitter uses Atom while Delicious uses RSS, you'll notice that the syntax is slightly different. There are also two Literal controls which we'll use for error catching in case either of the feeds ever has a problem.

    // Recent Tweets

    <%# (Container.DataItem as System.Xml.XmlNode)["content"].InnerText%>

    <%# DateFormat((Container.DataItem as System.Xml.XmlNode)["published"].InnerText)%> by <%# TwitterName((Container.DataItem as System.Xml.XmlNode)["author"].ChildNodes[0].InnerText) %>

    // Recent Bookmarks

    <%# (Container.DataItem as System.Xml.XmlNode)["title"].InnerText%>

    <%# DateFormat((Container.DataItem as System.Xml.XmlNode)["pubDate"].InnerText) %> by <%# (Container.DataItem as System.Xml.XmlNode)["dc:creator"].InnerText %>

    In our code-behind file, all we're doing is creating an XmlDocument object and binding our repeaters to it. The Delicious feed works by default but since the Twitter feed uses Atom we need to invoke the XMLNamespaceManager object and load the Atom definition. The Try/Catch blocks just ensure that the feeds are working and if not, display the error message instead.

        public string twitterUrl = "http://search.twitter.com/search.atom?q=asp.net";
        public string deliciousUrl = "http://feeds.delicious.com/v2/rss/tag/aspnet?count=15";
    
        public System.Xml.XmlDocument doc;
    
        protected void Page_Load(object sender, EventArgs e)
        {
            doc = new System.Xml.XmlDocument();
    
            try
            {
                doc.Load(twitterUrl);
                XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable);
                nsMgr.AddNamespace("def", "http://www.w3.org/2005/Atom");
                rptTwitter.DataSource = doc.SelectNodes("/def:feed/def:entry[position()<=5]", nsMgr);
                rptTwitter.DataBind();
            }
            catch
            {
                rptTwitter.Visible = false;
                ltlTwitter.Visible = true;
            }
    
            try
            {
                doc.Load(deliciousUrl);
                rptDelicious.DataSource = doc.SelectNodes("/rss/channel/item[position()<=5]");
                rptDelicious.DataBind();
            }
            catch
            {
                rptDelicious.Visible = false;
                ltlDelicious.Visible = true;
            }
    
        }
    

    Lastly, since the client wanted the dates to display as "3 hours ago" instead of the actual date and time, the following function handles that. There's also a very simple function to pull the Twitter user name.

        protected string DateFormat(string rawDate)
        {
            DateTime currentDate = DateTime.Now;
            DateTime itemDate = DateTime.Parse(rawDate);
    
            TimeSpan difference = currentDate - itemDate;
    
            string dateValue;
            if (difference.TotalSeconds <= 60)
            {
                dateValue = difference.Seconds + " seconds ago";
            }
            else if (difference.TotalMinutes <= 60)
            {
                dateValue = difference.Minutes + " minutes ago";
            }
            else if (difference.TotalHours <= 24)
            {
                dateValue = difference.Hours + " hours ago";
            }
            else
            {
                dateValue = difference.Days + " days ago";
            }
    
            return dateValue;
        }
    
        protected string TwitterName(string rawName)
        {
            return rawName.Substring(0, rawName.IndexOf(" "));
        }
    

    That's it. Simple, but it works. You can download a zip of these files to use if you like. It also contains some very basic CSS and an OutputCache declaration so that the page isn't hitting external URLs on every single page load.

    Credit where credit is due... I hit up others sites, blogs, and forum posts to get ideas for how to do this and pulled together bits and pieces from various places. So thanks to the development community at large for always sharing information like this. I hope this post helps someone else as well.

    Sitefinity - The only CMS I've ever loved

    Bookmark and Share

    I've blogged a couple of times about why I don't like content management systems and their hidden costs. While I may not like them, every client I've had in the last year or two has asked for one. It appears that the days of websites being maintained by web developers are drawing to a close. So if every project requires a CMS then the only option is to find the best one and after using dozens of others, Sitefinity by Telerik is the hands-down winner for me.

    My main gripe with content management systems is that they're not intuitive at all for the end users who actually maintain the site. Drupal, for example, can be a very robust and powerful system... but God help you when Betty from accounting tries to use it. Let's be honest... the people that end up maintaining a site aren't always properly-trained, tech-savvy individuals. Often, it's a person with no web experience and minimal computer skills. When that's the case, as it often is, the CMS should be as user-friendly as possible.

    In my opinion, the user interface is where Sitefinity excels. Sure, it's got built-in forums, blogging capabilities, an events calendar, etc., etc., but what really sets it apart from other systems is it's drag-and-drop, click-to-edit, so-easy-a-monkey-could-do-it, interface. Compare the screenshots below of Drupal's basic interface with Sitefinity's and it's easy to see which will be easier to use.

    Drupal

    Sitefinity

    While Sitefinity has a ton of features built in, the other great thing about it is that it's built as a native ASP.NET application so the learning curve is drastically reduced for Microsoft developers like me. The ability to build your own user controls and tap into the robust API also make it easy to extend the CMS functionality to suit any client's needs.

    Lastly, Sitefinity CMS also has one of the best support teams I've ever worked with.  I've posted various messages in the support forums and the responses are always incredibly helpful and friendly. 

    Bottom line... Sitefinity has a price tag of $899 and a feature set that rivals systems costing 20-30 times as much making it one of the best values around.  If you've looked at other CMS products and been disappointed, I highly recommend you give Sitefinity a try.

    Basic CSS Forms with Row Highlighting

    Bookmark and Share

    A friend of mine recently asked me about creating forms with XHTML/CSS and since I've been recycling some simple form code for a while now I thought I'd share it.  I've also seen a lot of sites that are standards-compliant that still use tables to layout their forms when it's not all that difficult to do it with some CSS... so here's a basic demo.

    First off, we'll have some HTML for our form... Basically what we're going to do is wrap our form fields and labels (because all fields need associated labels) in some div and span tags which we'll then style with CSS.

     

    Next we'll use some CSS to float the labels and form fields next to each other and give them a simple background color.

    div.formRow { width: 550px; overflow: hidden; clear: both; margin: 0 0 3px 0; padding: 5px 0; font-size: 12px; background: #efefef; }
    	div.formRow span.formLabel { width: 125px; font-weight: bold; text-align: right; float: left; }
    	div.formRow span.formControl { width: 405px; text-align: left; float: right;  } 
    	div.formRow textarea { width: 300px; height: 120px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; }
    	div.formRow input.formButton { background: #666; font-weight: bold; color: #fff; }
    	div.formRow label { display: inline !important; }
    	.currentRow { background: #ffc !important; }
    
    

    Lastly, we'll use a simple jQuery function to highlight the row of the form field you're in. This works by applying/removing a CSS class when you click in/out of form elements. I use a class of "focusable" on the form field itself as the selector for jQuery to find and apply the function.

    	$(function(){
    		$('.form .focusable').focus(function(){
    			$(this).parents('.formRow').addClass("currentRow");
    		}).blur(function(){
    			$(this).parents('.formRow').removeClass("currentRow");
    		});
    	});
    

    That's it. Note that this is a pretty simple example. It doesn't include any validation or tooltip descriptors of form fields and certainly isn't meant to be the definitive guide on CSS forms. It's just some simple code that you can use a starting point to get a nice looking form up very very quickly.

    See a demo of this CSS form code in action.

    Xenocode Browser Sandbox - Run any browser from the web

    Bookmark and Share

    I've blogged before about services such as BrowserCam which you can use to test your websites across browsers and platforms. Screen capture services are increasingly hard to use since many websites these days rely on JavaScript and AJAX functionality which can't be tested by a screenshot. Remote access solves that problem but that can often be time consuming and tedious. Wouldn't it be great if you could just run the browser on your machine?

    Thanks to Xenocode's browser sandbox you can do just that. Xenocode is an application virtualization system that allows developers to make their applications available in virtual executables that can be deployed pretty much anywhere, such as via the web or on a USB key. It's pretty cool technology and as a showcase, they currently have a browser area where you can run multiple browsers simultaneously without having to install them on your machine.

    This browser sandbox doesn't have the myriad of browser/platform combinations that BrowserCam offers but let's face facts... most of us developers spend the majority of our time trying to make sure that our sites and apps work in IE6. Xencode will let you open IE6 (as well as 7 and 8) right on your desktop so that you can easily test, tweak, and troubleshoot your code. It's a great asset to any developer's toolbox.

    Visit the Xenocode Browser Sandbox

    Code Scene gets a facelift

    Bookmark and Share

    It's hard to believe that I started this blog way back in 2005. Several years later I decided it was time to give Code Scene it's first ever "redesign". I use the term redesign lightly since A) I am definitely not a designer and B) it doesn't look radically different than before.

    Here are a few of the changes on the site:

    I'm still making some tweaks and adjustments to the site but let me know what you think or if you find something wrong.

    Aptana Studio makes jQuery so much easier

    Bookmark and Share

    I use Dreamweaver for XHTML/CSS work and Visual Studio for ASP.NET.  You can say what you want about either of them or about the purity of hand-coding in Notepad, but the reason I use programs like that is primarily because of their "intellisense" and code-complete features.  I still hand-code all my XHTML & CSS but using Dreamweaver allows me to type the code exponentially faster.  I type "m" and it fills in "argin" for me.  This might seem trivial but when you spend your life at the computer this adds up to thousands of saved keystrokes a week.  Code completion features can also be a great learning tool for junior developers and developers getting used to a new language.

    Pretty much every web project I've done recently has involved some sort of jQuery coding.   There are some plugins available for Dreamweaver and Visual Studio to add code-complete for jQuery but as of this writing I haven't found any that I love.  Enter Aptana Studio.

    Aptana Studio is full-featured IDE with a vast array of features for coding in XHTML/CSS, PHP, Ruby on Rails, Python, and more.  It also features integrated FTP, JavaScript debugging with Firebug, a DOM navigator, and complete set of database tools.   It's a fantastic program, it runs on Windows, Mac, and Linux, and best of all… it's free.  (There is a $99 "Pro" version for hardcore users but the free version has an incredible feature set)

    So while there are dozens of reasons to give Aptana a download, the reason I love it right now though is because it has an awesome code assist function for jQuery.   For those of you not using jQuery it also supports and/or has plug-ins for Prototype & Script.aculo.us, Dojo, Ext JS, YUI, MooTools, and pretty much anything else you can imagine.

    Here's how to enable code assist for jQuery in Aptana Studio

    • Open Aptana Studio
    • Click Window > Preferences
    • Expand the Aptana node, then the Editors node, then the JavaScript node
    • Click on Code Assist
    • Check the boxes for libraries you wish to use
    • Click Okay and restart the program

    Overall Aptana Studio is a great program and a viable alternative for other development environments, especially if you don't want to shell out hundreds of dollars to Adobe or Microsoft.

    Download Aptana Studio here.

    Free the web - Boycott Internet Explorer 6