As we saw in a previous post, Modernizr allows you to work with the new HTML 5 elements, like nav, and still support browsers that don't know anything about a nav, or HTML 5.
However, HTML 5 is more than just a few dozen semantically meaningful elements. There are WebSockets, WebWorkers, WebStorage, and a number of other features that are interesting from a programmability perspective (not to mention all new CSS3 capabilities). The questions is: how do you know if a specific user's browser supports a particular feature?
For years we've relied on browser sniffing (user agent sniffing) to determine browser capabilities, but user agent string are often manipulated, sometimes misleading, and constantly mutating. If you truly want to know if a browser supports a particular feature, like local storage, then the most honest answer you'll receive is by interrogating the browser directly with script.
In other words - if you truly want to know if a browser is a duck, then ask it to quack.
When Modernizr loads, it executes a series of tests to see what features the environment supports. For example, here is the test for canvas capabilities:
tests['canvas'] = function() { var elem = document.createElement('canvas'); return !!(elem.getContext && elem.getContext('2d')); };
There are presently over 40 tests, from applicationcache to webworkers. The result of each test is made available on the Modernizr object for easy access from script. If you want to know if canvas is available, for example, you can just ask Modernizr.
if (Modernizr.canvas) { // do something canvasy }
If you want to see all the available test results, try out my featureDump. This uses underscore and jQuery templates, excerpt below, to grab all the Modernizr test results.
$(function () { var featureMap = _(_.keys(Modernizr)) .chain() .filter(noFunctionsOrPrivates) .map(toNameAndResult) .sortBy(name) .value(); function noFunctionsOrPrivates(key) { return typeof Modernizr[key] !== "function" && key.substring(0, 1) !== "_"; } function toNameAndResult(key) { return { "name": key, "result": Modernizr[key] }; } function name(feature) { return feature.name; } $("#mainTable").tmpl({ "feature": featureMap }) .appendTo($("body")); });
The code should produce a table like the following:
In addition to adding test results as properties to the Modernizr object, Modernizr also adds the test results as classes to the root html element. This is a technique used by several libraries to write CSS rules that apply to specific environments. In a live DOM explorer (what you get with Inspect Element in Chrome), you can see these classes.
Notice that if a test passes, you get the test name (canvas). If a test fails, you get a "no-" prefix (as in no-touch). These classes are useful if you want to write CSS style rules that will only apply themselves to browsers that implement (or don't implement) a specific feature.
.no-cssgradients body { /* styles */ } .cssgradients body { /* styles */ }
If a browser does not implement a particular feature – you don't always have to give up. In a future post we'll look at how Modernizr's script loading capabilities can combine with polyfills to bring some old browsers up to speed.
The Task Parallel Library is a joy to work with – it's easy to use and thorough. Recently I was using Parallel.ForEach to process a large collection, but wanted to stop processing early, across all threads, if an individual item met specific criteria. It's as easy as adding a ParallelLoopState parameter to the action body.
var result = Parallel.ForEach(messages, (message, loopState) => { if (message.IsOneThatStopsProcessing) { loopState.Stop(); } // ... // other processing // ... outputStack.Push(message); });
You can halt processing early by calling either Break or Stop on the loop state parameter. Break is for ordered collection where you want to halt at a specific location.
Modernizr.js is a little library that will help "modernize" old browsers.
As an example, let's say you create a new ASP.NET MVC 3 application with the "Use HTML 5 semantic markup" checkbox selected. If you peek into the layout view for the app, you'll find the following markup:
<nav> <ul id="menu"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("About", "About", "Home")</li> </ul> </nav>
The nav element represents a section with navigation links, and is a new element in the HTML 5 spec. The idea is that using nav gives more meaning to the page, and allows user agents like screen readers to identify navigation information (contrast nav against using a regular div element as the container - a div carries relatively no semantic value by itself).
There is a problem, however. Older versions of Internet Explorer (anything before version 9) do not recognize the nav element. IE refuses to apply style rules to unidentified elements, and will also not allow unidentified elements to have children in the DOM. If you have to support older versions of IE this will sound like a dire situation, but it turns out there is an easy solution.
You can "register" elements in IE using document.createElement. For example…
document.createElement("foo");
... is all you need to do for IE to apply style rules to <foo> elements, and construct them appropriately in the DOM. Years ago Remy Sharp created the html5shiv project, which was the first library to essentially execute createElement for all of the new HTML 5 elements, including nav, article, footer, header, etc. html5shiv then allows IE to recognize all HTML 5 elements.
Modernizr also "registers" all HTML 5 elements, meaning the HTML 5 MVC web application you build will work just fine on older versions of IE (as long as you leave Modernizer in your layout view). One note: you'll want to keep the script tag for Modernizr inside the <head> element. All the calls to createElement for new elements must happen before IE reaches the <body> tag.
Enabling HTML 5 elements is just one of the features Modernizr provides. In future posts we'll look at Modernizr's ability to detect features, and inject fallback scripts.
When I was making the switch from C and assembly to C++ I did quite a bit of reading on object oriented programming. It's hard to find material on OOP that doesn't praise the classical pillars of encapsulation, inheritance, and polymorphism. In the early years these three pillars were advertised as solution to all the ills of software development. Object oriented programming was my first "silver bullet" experience in the software industry.
OOP has been successful. The majority of the today's most popular programming languages support classical OOP techniques as first class language features. The techniques have even pushed their way into languages like Perl and PHP, and developers including myself have used OOP to build frameworks, applications, and libraries for desktops, devices, and the web.
So then, why did I recently debate an old friend about the decline of OOP?
My friend is die hard OOP proponent. He recognizes some of the flaws in the classical OOP principle of inheritance, but for him OOP is the hammer for every nail. He proposed that the most successful UI frameworks he's ever used are all built using classic OOP principles, and therefore objects afford the most modular, reusable, and extensible software possible.
I had some time to think about this argument on a recent flight to Norway, and I think holding up frameworks like Swing and Silverlight (or to go back in time, MFC and OWL) isn't fair. You can always find places where a certain paradigm is the best solution, and for application frameworks in general, and UI frameworks in particular, OOP might have found a sweet spot. A sweet spot because UI frameworks represent an alternate reality. The architects and developers get to make the rules of the reality, and implement the code. Where else but in a UI framework can you find a workable inheritance hierarchy 9 layers deep?
It's not that UI frameworks don't face constraints. There are performance constraints, memory constraints, video constraints. Still, UI frameworks are far away from the messy (and sometimes absurd) realities of the physical world. It is the application code where IS-A relationships are difficult to find and break down quickly. It is application code where roles and responsibilities are difficult to classify and harden into code because domain knowledge can span decades and domain experts will evolve the rules with every passing fiscal quarter.
It's in application code where I've found, over the last few years, that modularization and reuse come about easier by going very big, or going very small. Big in the form of web services, where you can hide an entire platform behind well defined interfaces and standards. Small in the form of functions with well defined meanings, clean inputs and outputs, and nothing but a black box in-between.
Classes? They get stuck in the middle. There is no generally accepted standard even within a single programming language like C# on how to approach class design, or how to consume a class. Do I inherit from it? Create it with the constructor? Use a factory methods? Use a factory object? Call into the base class method override before I do my work? Or After? Too many choices make simple chores complicated.
Look again at the list of the most popular programming languages and see how many languages support more than a single paradigm. It's not that OOP has failed, or is failing. It's just easy to see the other choices now that the silver has worn off the bullet.
Imagine (or dream) that you have some IronRuby code to execute.
require 'net/telnet' host = Net::Telnet.new(:Host => 'localhost') #... #... #... return data
One way to execute the code and capture the result is to use Execute<T> on the ScriptEngine object.
public T Execute<T>(string fileName) { var script = File.ReadAllText(fileName); var engine = IronRuby.Ruby.CreateEngine(); engine.SetSearchPaths( SearchPaths // will contain paths like: // @"C:\Program Files (x86)\IronRuby 1.1\Lib\ironruby" and // @"C:\Program Files (x86)\IronRuby 1.1\Lib\ruby\1.9.1" ); var result = engine.Execute<T>(script); return result; }
However, if you want syntax checks and error messages with line numbers, you'll need to take a couple additional steps. First, define a class that derives from the abstract ErrorListener class in Microsoft.Scripting.Hosting. The ErrorReported method can provide details about errors.
public class ReportingErrorListener : ErrorListener { private readonly TextWriter _writer; public ReportingErrorListener(TextWriter writer) { _writer = writer; } public override void ErrorReported( ScriptSource source, string message, SourceSpan span, int errorCode, Severity severity) { _writer.WriteLine("Error starting at line {0} column {1}", span.Start.Line, span.Start.Column); _writer.WriteLine(message); } }
Now you can create a ScriptSource from the Ruby file, and use the ScriptSource object to Compile and Execute the result.
public T Execute<T>(string fileName) { var engine = IronRuby.Ruby.CreateEngine(); engine.SetSearchPaths(SearchPaths); var source = engine.CreateScriptSourceFromFile(fileName); source.Compile(new ReportingErrorListener(Console.Out)); var result = source.Execute<T>(); return result; }
The second part of my C# fundamentals course is available for subscribers on Pluralsight.com.
Part 2 introduces you to the variety of programming styles supported by the C# language. At its core, C# is an object-oriented, statically-typed language that lends itself to procedural and object-oriented programming, but recent additions to the language have made it much easier to develop using other programming paradigms, most notably, dynamic. This course covers object-oriented programming, functional programming, the dynamic language runtime, LINQ programming, and software craftsmanship.
The section on crafting C# code includes my current top 10 rules for writing better C# code, which was fun to record.
Enjoy!
Someone asked about the circular div I used for magnification in an earlier post. There are no primitives in CSS for building arbitrary shapes, but like most things on the web, that doesn't stop anyone from trying.
For example: don't think of a circular div as a circle. Think of a circular div as a square with heavily rounded corners.
Given this markup:
<div class="circle-small"> <p>Hello!</p> </div>
And this CSS:
.circle-small { width:100px; height:100px; border-radius: 50px; background-color: #cccc99; } .circle-small p { text-align:center; font-weight:bold; padding-top:40px; }
You can present the following content (assuming the user agent supports border-radius):
Try it here: http://jsfiddle.net/Jh2Nd/
But the fun doesn't stop with rounded corners. A long time ago someone looked at how the a browser renders borders and noticed a particular angle in the output, which gives us another "primitive" we can use to create shapes, like a triangles:
<style> .triangle-blue { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-bottom: 50px solid blue; } </style> <div class="triangle-blue"></div>
Which renders:
Try it here: http://jsfiddle.net/NCxEQ/
Once you have some primitives in hand, it's only a matter of inspiration until someone creates a house: http://www.designdetector.com/tips/3DBorderDemo2.html
Add in some CSS 3 transformations, and now you can have trapezoids, stars, hearts, and infinity symbols. See: The Shapes of CSS.