Skip to a section of this page:

Archive for March, 2009

Not-so-compact documentation

Monday, March 30th, 2009

I just finished fleshing out the documentation for the compact content widget.

In particular, now each presentation type (tabbed, slideshow and slider) has its own page, that outlines:

  1. How to use that presentation type.
  2. Options that can be set independently for each widget instance.
  3. Configuration that applies globally for all instances of a particular presentation type.
  4. The markup generated when a widget is initialised.

The documentation is fairly detailed, but hopefully this level of detail is useful.

Who started it?

Wednesday, March 25th, 2009

I spent some time this evening thinking about ideas for progressing form validation code.

Specifically, I was trying to solve the conundrum: When the submit event for a form is triggered, how can you tell which user interface element triggered the event?

This problem typically arises when you have multiple submit buttons on a form, when any submit button is activated, the submit event is triggered, but the form element is passed as a property of the event object, not the element (in this case a button) that originally triggered the event.

To complicate matters further, pressing enter while focussed on any input element will also trigger the submit event in many user agents.

Finding a complete robust solution became a bit of an emotional roller-coaster, let me explain…

  1. My initial investigation revealed that jQuery was returning a useful object eventObj.originalEvent.explicitOriginalTarget. :)

    For example:

    $('form').submit(eventObj) {
    	var iStartedIt = eventObj.originalEvent.explicitOriginalTarget;
    };

    Unfortunately, it turned out that explicitOriginalTarget is a Mozilla-specific property, with no cross-browser alternative. :(

  2. My next thought was that the currently focussed element would have to be the element that triggered the submit event! :)

    Unfortunately, jQuery doesn’t have a :focus selector. :(

  3. I found a proposed solution for extending jQuery with a :focus selector. :)

    Unfortunately, it relies on document.activeElement, which is a property only supported in IE, and modern browsers that have implemented parts of the HTML5 draft specification. :(

  4. Luckily, a good fellow proposed a way to support document.activeElement in older browsers that don’t implement it themselves. :)

    And… even better, this seemed to work (well, mostly – see below).

All together now

So put all this together and we get:

// Add document.activeElement support to browsers that don't support it.
if (
	typeof document.activeElement == 'undefined' &&
	document.addEventListener
) {
	document.addEventListener("focus", function(e){
		if (e && e.target) {
			document.activeElement = e.target == document
				? null : e.target;
		}
	}, true);
}
// Extend jQuery to support :focus selector
jQuery.extend(jQuery.expr[':'], {'focus': function(e) {
	return (document.activeElement)
		? e == document.activeElement : false ;
}});
// Now on submit, we can find the element that triggered this event
$('form').submit(function(eventObj) {
	// if a submit button triggered the submit event, find it
	if ((focussedSubmit = $(this).find(':submit:focus')).size() > 0) {
		var iStartedIt = focussedSubmit;
	} else {
		// otherwise find the first submit button
		var iStartedIt = form.find(':submit').eq(0);
	}
	// The iStartedIt variable now contains a reference to the element
	// that triggered the submit event!
};

Tested and working in Firefox 2, Firefox 3, Opera 9.5 but not working correctly in Chrome. IE versions were not tested at this time, but in theory IE6+ should be fine.

First contact

Sunday, March 8th, 2009

I finally have a contact form! Thanks to the close-to-perfect WordPress plugin Contact Form 7.

I say “close-to-perfect” because of two fairly minor flaws (these observations are based on WordPress v2.7.1 and Contact Form 7 v1.9.3)…

Flaw the first: Accessible form markup

The plugin seems to output a bunch of non-semantic markup (<span>s, etc…). I’m just going to ignore them because I figure they aren’t doing too much harm.

The bigger issue is that using the default form template, form control labels aren’t marked-up using the <label> tag! This issue has an easy fix, because the plugin’s author iDeasilo has thoughtfully allowed for customising the output markup.

Here’s the template markup I settled on:

<div id="contact-form">
<p class="instructions">Required fields are marked with
<abbr title="(required)" class="req">*</abbr></p>
<ul>
	<li class="input required"><label for="your-name">Your Name
		<abbr title="(required)" class="req">*</abbr></label>
		[text* your-name id:your-name]</li>
	<li class="input required"><label for="your-email">Your Email
		<abbr title="(required)" class="req">*</abbr></label>
		[email* your-email id:your-email]</li>
	<li class="input"><label for="your-subject">Subject</label>
		[text your-subject id:your-subject]</li>
	<li class="input"><label for="your-message">Your Message</label>
		[textarea your-message id:your-message]</li>
	<li class="submit"><strong>[submit "Send"]</strong></li>
</ul>
</div>

I also added the following CSS to my stylesheet to make the form prettier:

#contact-form ul,
#contact-form li {
	margin: 0;
	padding: 0;
	list-style-type: none;
	overflow: hidden;
	zoom: 1; /* For IE6&7 */
	margin-bottom: 1em;
}
#contact-form li {
	position: relative;
	padding-left: 1em;
}
#contact-form label {
	float: left;
	clear: left;
	width: 10em;
	margin-bottom: .2em
}
#contact-form input,
#contact-form select,
#contact-form textarea {
	float: left;
}
#contact-form .submit {
	padding-left: 11em;
}
#contact-form abbr.req {
	color: #f00;
	font-weight: bold;
}
#contact-form .required abbr.req {
	position: absolute;
	left: 0;
	top: .2em;
}

The markup and style above are based on forms code ideas Ben and I have been refining for the last few years (which in turn are based on ideas from other web developers far and wide, I’m sure Ben will post about it in more detail later).

This version works well for a simple form like this. The form controls wrap under the labels at smaller resolutions, and the required field indicators always sit in their own column.

If you are a purist, you can separate the zoom: 1; line into a separate stylesheet and serve it to IE6 and 7 only using conditional comments.

Flaw the second: Automatic addition of <br /> to output

This issue is a little prickly, because there’s no way to turn this “feature” off in the plugin configuration.

A workaround has been suggested, thanks Aiden!

Unfortunately, implementing this workaround means I would need to remember to edit this file every time I update the plugin.

I have a slightly different solution, based on Aiden’s idea that means the plugin can be updated and this preference should remain intact.

Because the plugin checks to see if the constant is defined before setting it, if we set the contstant first, our value will not be overwritten by the plugin.

Add the following code to the top of your wp-config.php file:

// Contact Form 7 plugin: Don't add <br /> tags!
	define('WPCF7_AUTOP', false);

Remember to keep this part of the wp-config.php file when you next upgrade WordPress.