Forum Moderators: not2easy

Message Too Old, No Replies

progressive enhancement

huge drop down nav menu

         

tonynoriega

10:32 pm on Dec 29, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



ok, i am taking into account more of PE when designing new elements to my site.

i want to try now to incorporate a huge navigation drop down menu.

i see some that look like there are either divs inside, or a small table.

i think divs would work best.

a few seem to use jquery or something similary like moo tools.

where do i start to make this work.

do i just code a simple CSS drop down menu first then adapt it to any javascript i want to implement?

what if modifying the drop down to work with the javascript, causes it to fall apart without it?

i understand teh concept of PE, but not sure i get the steps involved.

rocknbil

8:06 pm on Dec 31, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Figured someone else would pick this up. But here's how you approach it.

Build it so it works without the enhancements. Two examples:

<p><a href="tos.html">Terms of Service</a></p>
<form method="post" action="contact-us.php">
<!-- typical form fields -->
<p><input type="submit" value="Submit"></p>
</form>

All that has to work without Javascript: server side-validation of the input, etc. Okay, enhance it:


<p><a href="tos.html" onClick="return newWin('tos.html',600,500);">Terms of Service</a></p>
<script type="text/javascript">
function newWin(url,width,height) {
var day = new Date();
var id = day.getTime();
var params = 'width='+width+',height='+height+',scrollbars,resizable';
var win=open(url,id,params);
return false;
}
</script>

Now how does this work progressively? Per the first example, you know it works without JS. In the above, the return false is important. It's what stops the parent page from navigating to the href in the link when clicked.

So if JS is enabled, a new window opens, if not, the content is still accessible. And that's the important part.

Note also, in my example I have the resizable and scrollbars attribute included. Too often designers are more concerned about their design than possible different environments that kill the accessibility of the new window. Unless the window is resizable and has scrollbars, they might not be able to access all the content.

Example two, the form.


<form method="post" action="contact-us.php" onSubmit="return validate(this);">
<!-- typical form fields -->
<p><label for="email">Email:</label>
<input type="text" name="email" id="email" value=""></p>
<p><input type="submit" value="Submit"></p>
</form>
<script type="text/javascript">
function validate(form) {
var msg = '';
if (form.email.value=='') {
msg = 'Please enter your email address.';
}
// etc . . . concatenate to msg if other errors
if (msg!= '') { alert(msg); }
else { form.submit(); }
return false;
}
</script>

Return false works in the same way - it stops the form from submitting and allows the Javascript to manage it. But there's a hidden bonus here, one often overlooked: Note the event handler is attached to the form itself, not the button.

Often you'll see events attached to the button, or input type="button," and button types have no inherent actions on their own. What if someone presses the enter key while in the email field? It will bypass your Javascipt and submit the form.

By putting it on the form itself, this insures when the form submits, it will pass the event to the Javascript. And as you already know, the form works fine without Javascript because you did that first.

Now let's even go one step futher: let's make the progressive JS unobtrusive. That is, remove all the inline JS from both examples, and attach events to them.

In the head of the document,

<script type="text/javascript" src="myscript.js"></script>

Then we move our functions inside myscript.js, with one added bit. Note 1) no script tags required in an external script, and 2) the window.onload, which attaches the events to the ID'ed elements:


window.onload=function() {
if (document.getElementById('my-form')) {
document.getElementById('my-form').onsubmit=function() { validate(this); };
}
if (document.getElementById('my-link')) {
document.getElementById('my-link').onclick=function() { newWin(this.href,600,500); };
}
; // <-- not a typo, ends function statement
function validate(form) {
var msg = '';
if (form.email.value=='') {
msg = 'Please enter your email address.';
}
// etc . . . concatenate to msg if other errors
if (msg!= '') { alert(msg); }
else { form.submit(); }
return false;
}
function newWin(url,width,height) {
var day = new Date();
var id = day.getTime();
var params = 'width='+width+',height='+height+',scrollbars,resizable';
var win=open(url,id,params);
return false;
}

And our form and link are now free of inline scripting:

<p><a id="my-link" href="tos.html">Terms of Service</a></p>
<form id="my-form" method="post" action="contact-us.php">
<!-- typical form fields -->
<p><label for="email">Email:</label>
<input type="text" name="email" id="email" value=""></p>
<p><input type="submit" value="Submit"></p>
</form>

A few notes:
-- The "if document.getElementById" part first checks that the item exists in the document, so if you don't have these elements on all pages, it will not error. This allows you to centralize your scripting.

-- Note the attach to the link uses this.href to "get" the link for the new window. So you don't need to hard code a link in your scripting. Additionally, if you did what many JS coders do,

<a href="#" onclick=" . . .
or
<a href="javascript: . . .

It wouldn't work. What I'm getting at is you can only arrive at this graceful solution by developing the unenhanced version first. Not the other way around, like much of what you see on the web. "Make it look cool, then make it accessible." NO. :-) Make it work first, then add the goodies.

-- In most cases you wouldn't actually use ID to access a link, especially since you expect to have a lot of them. You'd do so by class name or some other attribute, like any links inside an ID'ed element or something else . . . above is for example only.

So the bottom line: build it without the bells and whistles, then apply the dynamic enhancements.

i want to try now to incorporate a huge navigation drop down menu.

I think, unless you can't manage to work it out with pure CSS, the "unenhanced" content will be a smaller version. By that I mean, you may be able to use the hover: selectors to do this without even using Javascript, but maybe not.

i think divs would work best.

Switching gears for a moment, let's consider semantics. A <div> is a generic block element used to divide a page for layout when no other semantic element applies. They are often overused as well, a condition coined by swa66 as "div-itis".

What is a navigation of any kind? A list of links. So I'd suggest to use not divs, not tables, not anonymous <br> (or <br />, if you're actually using real XHTML in your output,) but an unordered list.

<ul>
<li><a href="link1.html">Link 1</li>
<li><a href="link2.html">Link 2</li>
</ul>

The overall summary is that all of this works together. Accessibility first, of which document semantics plays an important part, functionality without enhancements, then add enhancements.

a few seem to use jquery or something similarly like moo tools.

Correct,and most implementations will use an unobtrusive method to do so, attaching events to objects by class or ID. Which is good. And also which is why I dragged (drug?) you through this long tutorial, as you need to (should) understand all three to correctly work with those. :-)

swa66

9:52 pm on Dec 31, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'd do a drop down menu even those with those huge drop downs as a nested list.

Do it in a standards compliant browser using just html+css.

You won't need JS at all to get it working, but if you want e.g. smooth animation: add that in (optional) JS.

Then comes the MSFT curse on any designer "IE": IE8 and IE7 normally do a somewhat reasonable job, fix everything they need fixed in a conditional comment.
The por excuse for a broser that is IE6 is the worst of the bunch. If you still care about it will need scripted help for every drop down menu (:hover support is completely missing on anything but a <a>), so you need scripted help there. IE7.js is one way but there are less heavy solutions out there.

As to progressive enhancement: I might think of it that way for JS, but never for CSS: there the name of the game is graceful degradation: design for all you can using what you can as soon as you can and fix it for those still using the legacy browsers where you still care about them so it looks somewhat acceptable.
So yes, that means going for CSS3 rounded corners etc. Square corners mostly will work for those still using old browsers :)