Improvement to Filament Group’s Tooltip Script

26 Nov

I also made some improvements to the Filament Group’s tooltip script. The script already supports ARIA enabled tooltips. I added:

  • An additional “tooltip-hidden” class on closed tooltips
  • Support for tooltips added using AJAX in IE
  • Keyboard access to tooltips
  • Dynamic positioning of the tooltips

They keyboard access is designed mostly to be used with tooltips on link elements, though it only works on elements in the tab order. If you tab to the tooltip, you can hit the enter key to open the tooltip and either hit escape or tab to the next element to close it. One thing to note: this change required moving the inserted tooltip content from immediately before the close body tag to immediately after the tooltip trigger itself. This could result in incorrect HTML (albeit created by JavaScript), if you use a tooltip on something like a list item tag that has a strict containing element.

The dynamic positioning helps with displaying tooltips anywhere on the page. Previously they could run off the edge of the page if the tooltip was positioned too close to the edge. Now they default to the top-right corner of the trigger. If there’s not enough space on the page to the right, it will display to the left. Same thing with the top, where it flips to the bottom. You could end up with a tooltip in the top-right, top-left, bottom-left, or bottom-right. If the browser window is too small to fit any direction… well then you’re stuck.

You can find my changed version for download here.

Tags: , , ,

Improvement to Filament Group’s Collapsible Script

26 Nov

After using the Filament Group’s excellent collapsible script at work, I decided to make a couple of minor improvements to it. You can read more about it on their site, but in short it does a great job of providing an easy and accessible way to collapse sections of content.

I simply added a couple of tweaks. First, the ability to expand and collapse the content by using the right and left arrow keys, respectively, when focused on the trigger element. Previously you could only do this by using the enter key (which is equivalent to a click). Second, the ability to start the element collapsed instead of expanded. You can do this by passing the value “true” to the function when initiating the collapsible section:

$('h2').collapsible(true);

You can find my changed version for download here.

Tags: , , ,

Confirmation Dialogues Across Browsers

25 Nov

At some point I needed to check the page confirmation dialogs across multiple browsers. I wanted to see what the exact wording was for the “OK” and “Cancel” buttons. For your benefit, here are the results:

Internet Explorer 6:

[Cancel]“]Internet Explorer 6Internet Explorer 8:

[Cancel]“]Internet Explorer 9:

[Stay on this page]“]Safari 5:

[OK]“]Safari 5Chrome 13:

[Leave this Page]“]Chrome 13Firefox 5:

[Leave Page]“]Firefox 5

JATH as a Bookmarklet

14 Aug

JATH now has a documentation page over on Google Code: http://code.google.com/p/jath/wiki/Documentation.

More exciting, though, is that you can use JATH as a bookmarklet now. Just drag it to your bookmarks bar and check any page you like.

Tags: , , ,

Introducing JATH

7 Aug

In my current work as a government contractor I have to pay a lot of attention to accessibility in my web development. Because accessibility errors aren’t always immediately obvious to those of us who don’t use assistive technology, this can be a bit difficult.

So I wrote the JavaScript Accessibility Testing Helper, a basic JavaScript file which highlights accessibility errors on your page. Simply put jath.js and jath.css in your template and JATH will show up on every page on the site. Just be sure to remove it before production.

Fixing Overly Long Select Menus

15 Jul

If you’ve ever tried to style an HTML <select> tag, you know how hard it is to do. While you can, with some work, customize the <select> itself, the <option>s inside of it aren’t style-able. And the <option>s define the width of the select by default.

This means that if you have a very long option, then your <select> may end up  wider than its container. A Google search about this problem generally yields a few solutions:

  • Don’t use selects
  • Shorten your options
  • Use the CSS width attribute

Unfortunately, none of these really work. <select> is often the correct tag to use, sometimes you can’t shorten the options, and while setting the width does work, it also sets the width of the <option>s, making it so you can’t see the full text on the overly long ones.

There are some complicated solutions out there, such as this, but they often involve manipulating form elements, never a good idea where accessibility is concerned.

After a good bit of searching, I found this solution from Doug Boude, which is fairly ingenious. It sets the width attribute on a <select> to 100% of its container, thus limiting its size. But, when the <select> is opened, it sets the width to “auto” so that the options show full width. When you close the <select> it goes back to 100%. Brilliant!

I’ve updated it a bit to bring it in to a jQuery world. Below is all that you need. Put the CSS in your style sheet and the JavaScript on your page or in your main script file.

A  few things to note:

  • You only need to do this in Internet Explorer, as other browsers always show the full width <option>s. The script accounts for this.
  • Because we bind to the blur and change events to reset the width, if you open a select but close it without changing anything, you lose the drop down arrow until you click away. I find this an acceptable bug, but if anyone has any ideas on how to fix it, let me know.

CSS

/* Selects */
.constrain {width: 100%; overflow:hidden;}
.constrain select {width: 100%;}
.constrain.wide {width: auto;}
.constrain.wide select {width: auto;}

JavaScript

//Fix problem with select menu options getting cut off
/* Thanks to http://www.dougboude.com/blog/1/2008/05/Viewing-Option-Text-in-IE7-thats-Wider-than-the-Select-List.cfm */
// if the select is too wide, constrain it
jQuery('select').each( function() {
	if (jQuery(this).width() > jQuery(this).parent().width() && !jQuery(this).parent().hasClass('constrain')) jQuery(this).wrap("<div class='constrain'>");
});
// only for IE help out by changing the widths
if (jQuery.browser.msie) {
	jQuery('.constrain select').unbind().bind("mousedown keydown",function() {
		jQuery(this).parent().addClass('wide');
	}).bind("blur change",function() {
		jQuery(this).parent().removeClass('wide');
	});
}

Tags: , , , ,

Fieldsets and Legends in IE7

18 Jun

Background

(Skip the background, take me straight to the solution!)

For accessibility purposes, all radio button and checkbox groups should be put inside an HTML fieldset tag with a legend tag. This is because their is no label for the radio button group as a whole. Consider the following code:

<div>
	<p>A yes/no question?</p>
	<input type="radio" name="radio" id="yes" value="yes"/>
	<label for="yes">Yes</label>
	<input type="radio" name="radio" id="no" value="no"/>
	<label for="no">No</label>
</div>

The labels “Radio 1″ and “Radio 2″ select the respective radio buttons when click on. But if you navigated to this form element using a screen reader there is a good chance that you would miss the question entirely. To fix that, use a fieldset and legend:

<fieldset>
	<legend>A yes/no question?</legend>
	<div>
		<input type="radio" name="radio" id="yes" value="yes"/>
		<label for="yes">Yes</label>
		<input type="radio" name="radio" id="no" value="no" />
		<label for="no">No</label>
	</div>
</fieldset>

Now a screen reader will inform the user that the current input fields (yes and no) are part of “A yes/no question?” Much better.

Problem

Fieldsets bring along with them extra formatting in the browser. By default a  fieldset appears as a box with the inputs inside it:

You’ll note that the legend tag is positioned by default slightly off of the top-left corner. But what happens if we want to make the question horizontal, so we can fit it into a list of fields? This can be accomplished as so:

fieldset.radio legend {
	float: left;
	width: 30%;
}
fieldset.radio div {
	float: left;
}

Results:

There are still some spacing issues and a border, due to browser defaults on the fieldset and legend elements. Expanding our code:

fieldset.radio {
	padding: 0;
	border: 0;
}
fieldset.radio legend {
	float: left;
	width: 30%;
	margin-left: -2px;
}
fieldset.radio div {
	float: left;
}

See the example code. Results:

Looks pretty good, right? But that’s before we take it into Internet Explorer 7:

IE7 seems to have 2 issues:

  • It uses different default margins (7px left instead of 2px left) than other browsers
  • Left floated legends still force other elements to clear beneath them

The first problem we can solve fairly easily using a conditional comment. The second is more puzzling.

Solution

The best solution is to absolutely position the legend. This breaks it out of the normal flow of the document so it doesn’t mess with other elements. Then we have to give the div left padding of 33% so it is not under the legend. Why padding and not margin? Good question. IE7 doesn’t like margin, but padding works.

fieldset {
	padding: 0;
	border: 0;
}
legend {
	background-color: blue;
	margin-left: -2px;
	position: absolute;
}
fieldset.radio div {
	background-color: red;
	padding-left: 30%;
}

We also include some IE7 specific CSS to move the legend farther to the left:

<!--[if IE 7]>
<style type="text/css">
	fieldset.radio legend {
		margin: 0 0 0 -7px;
	}
</style>
<![endif]-->

Result:

We can turn on background color so you can see the location of the fieldset (blue) and div with radio group (red). See example code.

Other Solutions

There are several other solutions that produce similar results, though none are ideal. I include them below for reference.

1. Place the legend at the end of the fieldset and float the div right instead of left. This works, but we have to reorder are HTML and the containing element has to have an explicit width or the inputs end up on the far right. See example code.

2. Wrap the legend tag in a div and float that div. This seems to remove the core problem (presumably because the div, not the legend, is floated), but it still involves an HTML change. See example code.

3. Leave the legend how it is and reposition the div to the right and up, so it ends up in the correct place. This requires no HTML modification, but the degree of vertical repositioning is dependent on the font size and is thus tricky. See example code.

Conclusion

This seems to be a fairly workable cross-browser solution to get a horizontal fieldset that uses a legend. As demonstrated above, it works in IE7. It seems to work in IE6, and even back to IE 5.5, though I did not test thoroughly on those browsers. It also works in IE8 and IE9.

If you wanted to keep your code more consistent, you could use the standard float left for most browsers, and move the absolute positioning into the conditional comment for IE7 and below.

In order to get the legend in a pixel-perfect location across all browsers you might need to do a little tweaking on the margins, but this is pretty close. I hope you find it useful.

Tags: , , , , , , ,

Sapient Government Services

18 May

Since my last post was about a new job, it’s only appropriate that this one is too. I’m now an Interactive Developer at Sapient Government Services.

Short and concise. That’s how I roll. (Not.)

Bread for the World

7 Jun

On the off chance that there’s anyone actually watching these updates–I’ve moved to a new job.  I now work as the Online Communications Associate at Bread for the World, a collective Christian voice urging our nation’s decision makers to end hunger at home and abroad.

Incidentally, you can also now find me on Facebook and Twitter.

Interviewed on CNN

26 Aug

Yesterday evening I had the fascinating experience of being interviewed, along with several friends, by CNN International.  We watched Michelle Obama’s speech at the opening of the 2008 Democratic National Convention and gave our thoughts on it.  You can find the full story on CNN’s website.

Follow

Get every new post delivered to your Inbox.