Search Channels
 for 
 

What Credit Card Should I Get?

Online RSS Preview
(Content viewed with Online RSS Viewer; converting raw RSS feeds into nicely formatted webpages everytime!)
 
NETime Channel > Category > Internet > Snook.ca
 
 
Snook.ca
Show/Hide Channel Info RSS Channel Source Add To My Channels | Hide All Content Show All Content
 
Hide Channel Info Channel Info

snook.ca - a collection of tips, tricks and bookmarks in web development
Author : Jonathan Snook
Overview : A collection of tips, tricks and bookmarks in web development
Language : English
Last Updated : 7/28/2005
Website : http://www.snook.ca/jonathan/


View Channel View Channel

1. Project Detritus
Date/Time : 4/24/2012 10:38:16 AM
Direct link : http://feedproxy.google.com/~r/snookca/~3/wwSIh9XJZ7Q/project-detritus
 

Zielun asks of managing projects:

It often happens in projects that based on one, large system with tons of modules that can be enabled or disabled, and documentation is often not up-to-date or doesn`t exist at all. At least I have such experience. I know that real problem lies elsewhere like in project management but such things often plays main role when you or team decides which coding standard to pick for a project to solve such issues.

This project detritus can definitely be frustrating. Big projects that go on for extended periods of time begin looking like sediment layers of a rock formation. It becomes an interesting archaeological expedition as you chip away at the months (and years) of development and can almost pinpoint the time that a chunk of code was written based on the style it was written.

I've rarely seen a long running project maintain an absolutely rigid and consistent coding style. We make mistakes in the course of building a project, correct those mistakes, but rarely go back to correct the ill-conceived approaches used at the beginning of a project.

Nobody wants to clean out the cruft for fear of unsettling the foundation and having the entire project collapse on them.

A modular approach, a good naming convention, and an reduction of element selectors can make it much easier to determine what is and isn't being used on a project. Do a search for a module name and you'll discover right away if it is used and where it is used. Tools can be built to automatically review which classes are being used and which aren't.

This is easier to do if you keep styles in the CSS. Don't keep them inline and don't set them in script.

Why avoid element selectors? HTML can change but it's not as easy to tell if the CSS is being used or not unless you examine every instance. How relevant is #sidebar h2 if I've long since switched level 2 headings to level 3 headings?

To be clear, element selectors can be quite useful. Don't throw out the baby with the bath water. Just strike that balance between when to use an element selector and when adding a class would be cleaner, clearer, and more semantic.

Of course, I talk more about this in a little e-book I wrote...*ahem*



Back To Top Go To Bottom

2. CoffeeConsole: A Chrome Extension
Date/Time : 4/6/2012 10:14:06 PM
Direct link : http://feedproxy.google.com/~r/snookca/~3/7CgYPzcDttw/coffeeconsole
 

Harry Brundage, a co-worker of mine at Shopify, does a lot of CoffeeScript development and said he would love to be able to do CoffeeScript right from the console in Chrome's Web Inspector. I asked Paul Irish, a "dev relations guy" at Google, to point me in the right direction on building just such a thing.

The result of today's pet project is CoffeeConsole, a Chrome extension that adds a new panel inside the Web Inspector. Type in any CoffeeScript and then hit the run button (or hit Command-Enter or Shift-Enter). The code will be compiled into JavaScript and then run in the context of the current window.

I've put together a quick video to demonstrate this.

Behind the scenes, I cobbled together a bunch of resources. Namely, the Ace editor and the CoffeeScript compiler There really wasn't a lot of code that I needed to add except to figure out how to run the compiled JavaScript in the proper context.

There's definitely more features that can (and maybe should) be added such as the ability to review the compiled JavaScript and the ability to view the compilation errors. The project has been added to GitHub, so feel free to contribute. (As of writing this, I still need to choose a license but likely an MIT license.)

Download the extension or check out the repo on Github.



Back To Top Go To Bottom

3. Definition Lists versus Tables
Date/Time : 3/25/2012 5:40:41 PM
Direct link : http://feedproxy.google.com/~r/snookca/~3/C6TKssW3Wi4/definition-lists-v-tables
 

I remember a couple years ago speaking at An Event Apart and mentioning how I don't use the definition list. I may have said it a few times, to the annoyance of the audience. When pushed on why I don't use definition lists, I mentioned that screenreaders read out that a term is equal to a definition. Somebody tested and confirmed with me afterwards that his particular screenreader did in fact read it out in a way that would be awkward if people were to use them. (Alas, I can't remember exactly what it was that the screenreader actually announced.)

It's been a couple years since that fateful day and the situation came up at work. A co-worker was using a definition list and I mentioned the accessibility issue. A table was better. But was it? HTML5 indicates that definition lists are now data lists and can take any name/value content. Based on the spec, my co-worker was using the definition list correctly.

I decided to test which is better: a <dl> or <table>. In these tests, I'm using the only two screenreaders that I have available to me: VoiceOver (with Chrome 17 on Mac and Safari 5.1, both on Lion) and NVDA (Firefox 11 on Windows 7 via VMWare Fusion).

Game on!

The Design

The design is pretty typical: properties on the left, values on the right.

An Example Layout

The Definition List

I created a simple definition list.

<dl> <dt>Property</dt> <dd>Value</dd> <dt>Name</dt> <dd>Val</dd> </dl>

NVDA'S behaviour here is interesting in that it just reads the items without announcing that it's a list or that the terms and definitions have any relation. The content is just read in a linear fashion.

VoiceOver is better in that it informs you that it's a list but it says it is a list with 4 items. That's not very helpful. It doesn't establish any connection between the terms and their definitions.

Based on this alone, I'd say that the DL isn't a great idea. So, what of the table?

The Table

I created a simple table with two rows and two columns.

<table> <tbody> <tr> <td>Property</td> <td>Value</td> </tr> <tr> <td>Name</td> <td>Val</td> </tr> </tbody> </table>

NVDA nor VoiceOver provide any insight that this is a table. Once again, the content is simply linearized. This makes sense since tables are often used for layout instead of for semantics.

There are a few different approaches that can be used to inform the screenreader that it's a valid table and allow for a richer interaction experience.

Use header cells

Changing the keys to use a TH instead of a TD allowed the screenreaders to recognize that it was a table and navigate the table.

<table> <tbody> <tr> <th>Property</th> <td>Value</td> </tr> <tr> <th>Name</th> <td>Val</td> </tr> </tbody> </table>

Interestingly, although the table could be navigated and you'd have a sense of rows and columns, neither NVDA nor VoiceOver in Chrome would announce that a particular cell was a header cell. VoiceOver in Safari 5.1, however, would announce the value of the header cell when switching rows. "row 1 of 2 property value" with a long enough pause between the words property and value so as to be able to tell that it's describing the heading for the cell.

For NVDA, adding a scope attribute to the header cell would allow the heading to be announced.

<table> <tbody> <tr> <th scope="row">Property</th> <td>Value</td> </tr> <tr> <th scope="row">Name</th> <td>Val</td> </tr> </tbody> </table>

In this case, NVDA would say "property row 1 of 2 value".

ARIA Roles

The third approach I used was to specify the ARIA grid role to the table. This also required adding the row roles to each of the TRs.

<table role="grid"> <tbody> <tr role="row"> <th>Property</th> <td>Value</td> </tr> <tr role="row"> <th>Name</th> <td>Val</td> </tr> </tbody> </table>

Once again, NVDA and VoiceOver would read the cells but did not indicate any association between the header cell and the content cell. There are additional roles that can be applied on the cell—role="gridcell" and role="rowheader"—but neither provided any additional clarity to the screenreader.

Caption

The last technique to inform the screenreaders that the table was a table was to apply a caption to the table.

<table> <caption>Caption</caption> <tbody> <tr> <td>Property</td> <td>Value</td> </tr> <tr> <td>Name</td> <td>Val</td> </tr> </tbody> </table>

What I noticed was that the caption could be hidden using display:none and the table would still be navigable in VoiceOver. Unfortunately, with NVDA, setting the caption to display:none (or even just position:absolute) seems to render the table like a layout table. That's not good.

Other Options

In testing other options, the only other alternative that I could find that seemed particular relevant was to identify the heading. This could be done in one of two ways: use a heading tag or use a heading aria role.

With the heading tag, the heading level is announced.

With the heading ARIA role, it'll announce "heading level 0" in VoiceOver but just "heading" in NVDA. The document outline should be smart enough to figure out that the ARIA heading. However, in neither Safari nor Chrome was it able to automatically figure it out. Specifying an aria-level attribute should help clarify things. Unfortunately, while Safari recognized this attribute, Chrome didn't. Finally, NVDA recognized and read out "heading level 2" correctly.

Recommendation

Of all the options, I'd use one of two approaches:

  1. Use a table with scope attributes on header cells; or
  2. Use an ordered or unordered list (but not a definition list) with headings (tags or ARIA)

I like the way that lists are announced and would therefore lean in that direction. Tables offer a lot of features but for a simple list of name/value pairs, a table feels like too much. Here is how I would code up the example:

<ul> <li><h3>Property</h3> <div>Value</div> </li> <li><h3>Name</h3> <div>Val</div> </li> </ul>

Headings get floated to the left, divs get floated to the right, and list items clear floats. (Of course, use the proper heading level that is appropriate for your document.)

This was an interesting process to explore and I definitely have changed the way I would approach this in the future. Those with insights about other screenreaders are welcome to chime in.



Back To Top Go To Bottom

4. Going Simple with JavaScript
Date/Time : 3/5/2012 7:29:32 AM
Direct link : http://feedproxy.google.com/~r/snookca/~3/w_EFeuIwm1s/going-simple-with-javascript
 

I was making a change to a page that needed to pull from a remote API and make changes to various parts of the page. Sounds like the time to pull out jQuery and Ajax, doesn't it? Instead, I just used old fashioned JavaScript. Actually, I used new fashioned JavaScript.

Browsers haven't stood still in the advent of libraries and frameworks. As a result, we can take advantage of those features when we need to bake in a little extra.

Some JSONP

The first step was to get the JSONP call executing. This is generally straightforward: embed a script tag into the page. The script will run a function that you've defined on your page.

var scr = document.createElement('script'); scr.src = 'http://openexchangerates.org/latest.json?callback=formatCurrency'; document.body.appendChild(scr); 

When the script runs, it'll pass the data into the formatCurrency function. Excellent.

Once the data is in the function, I needed to grab all the elements of a particular type and make changes based on those.

querySelectorAll

The querySelectorAll method will grab all elements that match a particular selector—similar to jQuery. It's limited to selectors that the browser understands, which is definitely less than what jQuery can do. Sometimes a chisel will do in place of a sledgehammer.

The querySelectorAll method works in IE8 and up and all of the other popular browsers, too. I also wrapped my entire block of code to check if the browser supports this method before doing anything.

if (document.querySelectorAll) { function formatCurrency (data) { var els = document.querySelectorAll('.price'); /* do stuff with the elements */ } var scr = document.createElement('script'); scr.src = 'http://openexchangerates.org/latest.json?callback=formatCurrency'; document.body.appendChild(scr); }

As you can see in the example, all I'm looking for is every element that has a class of price. I could've used getElementsByClassName but that's not supported in IE8, whereas querySelectorAll is. So far, so good.

After that, it was just a matter of getting an attribute, making some changes and then re-inserting it into the DOM using innerHTML. Easy peasy.

Progressive Enhancement

But what of users who don't support this new fandangled functionality? It'll be the same as those who don't support JavaScript. In my case, it meant that users will see just Canadian pricing instead of converting it into their local currency.

Here's the final script in its entirety.

if (document.querySelectorAll) { var currencyLookup = { EUR:'€', USD:'US$', CAD:'CDN$' } function formatCurrency (data) { // format germany price var els = document.querySelectorAll('.price'); for (var i=0; i<els.length; i++) { var price = parseInt(els[i].innerHTML.replace(/[^0-9]*/,'')); var curr = els[i].getAttribute('data-currency'); var newPrice = price / data.rates.CAD * data.rates[curr]; els[i].innerHTML = '<small>' + currencyLookup[curr] + '</small>' + Math.round(newPrice); } } var scr = document.createElement('script'); scr.src = 'http://openexchangerates.org/latest.json?callback=formatCurrency'; document.body.appendChild(scr); }

That's a total of 628 bytes. No JavaScript libraries or frameworks required. That could be minified to 469 bytes. A far cry from the 91,000 bytes needed just to get jQuery on the page.

Take it easy

"Just use jQuery" might be the go-to phrase but, thankfully, you don't always need that much code to solve a simple problem. Pages are getting bigger and bigger. It's nice to know that we don't always have to use large resources to accomplish a small goal.



Back To Top Go To Bottom