A perfect faq page
This article was first published on tjkdesign.com (02-01-2006).
This is about using a Definition List and the DOM to create a nice FAQ page where clicking on the dt
s (the questions) "toggles" the associated dd
s (the answers).
(Note: If you're already using this solution, please check your version number (this is version 1.5.5). This latest version addresses a IE issue with images within DDs.)
This is what it does:
- Question 1?
- The vitality of conceptual synergies is of supreme importance exploiting the productive lifecycle working through a top-down, bottom-up approach. To focus on improvement, not cost, from binary cause and effect to complex patterns, while those at the coal face don't have sufficient view of the overall goals.
- Question 2?
- To focus on improvement, not cost, from binary cause and effect to complex patterns, while those at the coal face don't have sufficient view of the overall goals. To ensure that non-operating cash outflows are assessed.
- Question 3?
- The vitality of conceptual synergies is of supreme importance exploiting the productive lifecycle working through a top-down, bottom-up approach. To focus on improvement, not cost, from binary cause and effect to complex patterns, while those at the coal face don't have sufficient view of the overall goals. To ensure that non-operating cash outflows are assessed. The vitality of conceptual synergies is of supreme importance exploiting the productive lifecycle working through a top-down, bottom-up approach.
- Question 4?
- The vitality of conceptual synergies is of supreme importance exploiting the productive lifecycle working through a top-down, bottom-up approach. To ensure that non-operating cash outflows are assessed.
- Question 5?
- The vitality of conceptual synergies is of supreme importance exploiting the productive lifecycle working through a top-down, bottom-up approach. To focus on improvement, not cost, from binary cause and effect to complex patterns, while those at the coal face don't have sufficient view of the overall goals. To ensure that non-operating cash outflows are assessed.
The main advantages of the basic technique (related to the dl
):
- It uses semantic markup.
- It degrades nicely (hidden elements are visible in script-disabled UAs).
dt
s do not appear as links without script support.- It does not use inline event attribute (
onclick()
). - It does not require
a
elements in the markup. - It is screen-readers "friendly".
- It is keyboard "friendly".
- It is IE Mac compatible.
- It relies on one single hook.
- It allows the author to add/move/delete
dt
/dd
pairs easily (there is no variable in the script to edit and there are noclass
orid
to include nor change). - It is "powered" by a very light script (3Kb).
About the "Show All/Hide All" "links":
- they let the user expand all answers at once, so it is possible to search the document.
- they are hidden from Javascript-challenged browsers.
- they can be "Named Anchors", images or spans (actually they can be any inline elements or any other elements styled as inline).
This is more or less a plug-and-play solution (script and stylesheets are at the bottom of this page).
To make things work
1. Create a Definition List
Do not use more than one dd
per dt
; the markup for the one above looks like this:
<dl>
<dt>Question 1</dt>
<dd>The vitality of conceptual synergies...</dd>
<dt>Question 2</dt>
<dd>To focus on improvement, not cost, ...</dd>
<dt>Question 3</dt>
<dd>The vitality of conceptual synergies...</dd>
<dt>Question 4</dt>
<dd>The vitality of conceptual synergies...</dd>
</dl>
2. Assign a specific id
to your dl
<dl id="TJK_DL">
3. Download the files
Unzip the content of this ZIP File (3Kb) in the same directory as your FAQ page.
4. In your FAQ page, right above the closing head
tag (</head>
)
Cut and paste the following:
<script type="text/javascript" src="TJK_ToggleDL/TJK_ToggleDL.js"></script>
5. Call the script using the onload
event
<body onload="TJK_ToggleDL()">
Or, better, use a technique like the one explained here: executing JavaScript on page load.
6. Create 2 named anchors
In order to use the "Show All" / "Hide All" feature, you will need to create 2 named anchors with specific id
s (TJK_ToggleON
and TJK_ToggleOFF
). Dreamweaver users can take advantage of the "Named Anchor" icon in the toolbar to easily create the required markup. Dreamweaver will plug the name
attribute as well, but that’s OK, you can either delete it or ignore it.
This is the markup I’m using in this page:
<a id="TJK_ToggleON">Open All</a><a id="TJK_ToggleOFF">Close All</a>
Note that adjacent anchors are confusing in text-browsers.
You can also replace these Named Anchors with other inline elements, for example span
or id
(yes, images). Just make sure to set the proper id
s.
7. Hide links when JS is off
Because we want to hide those "links" from script-challenged UAs, you need to include the following rule somewhere inside your stylesheet:
#TJK_ToggleON,
#TJK_ToggleOFF {display: none;}
Note: You can also use a style
element to include this rule in the head
of your document (your FAQ page).
You’re done!. Feel free to edit the rules in the CSS file to fit your needs.
(Note: in case your questions are more than one line long, you may want to change this: "background:0 50%
" to this: "background:0 0
" and add “display:block
” to the #TJK_DL dt a {}
rule (to avoid any "wrapping").)
Latest news
- Hanz has created a recipe from this script for pmwiki users.
- Read this article in Italian on Javascript.html.it.
Content of the script and style sheets
TJK_ToggleDL.js
// Copyright 2006 | Thierry Koblentz - www.TJKDesign.com All Rights reserved
// TJK_ToggleDL() Version 1.5.4 report bugs or errors to thierry@tjkdesign.com
if (document.getElementById && document.getElementsByTagName){
document.write("<link href="TJK_ToggleDL/TJK_ToggleDL.css" type="text/css" rel="stylesheet" />")
document.write("<link href="TJK_ToggleDL/TJK_ToggleDL_ie5mac.css" type="text/css" rel="stylesheet" />")
}
function TJK_doToggleDL(x){
var zDD=document.getElementById('TJK_DL').getElementsByTagName('dd');
var zDT=document.getElementById('TJK_DL').getElementsByTagName('dt');
zDD[x].className=(zDD[x].className=='hideDD')?'showDD':'hideDD';
zDT[x].className=(zDT[x].className=='DTplus')?'DTminus':'DTplus';
}
//we open all of them
function TJK_ToggleDLopen(){
var zDD=document.getElementById('TJK_DL').getElementsByTagName('dd');
var zDT=document.getElementById('TJK_DL').getElementsByTagName('dt');
for(var i=0;i<zDT.length;i++){
zDD[i].className='showDD';
zDT[i].className='DTminus';
}
return false;
}
//we close all of them
function TJK_ToggleDLclose(){
var zDD=document.getElementById('TJK_DL').getElementsByTagName('dd');
var zDT=document.getElementById('TJK_DL').getElementsByTagName('dt');
for(var i=0;i<zDT.length;i++){
zDD[i].className='hideDD';
zDT[i].className='DTplus';
}
return false;
}
function TJK_ToggleDL(){
if (document.getElementById && document.getElementsByTagName){
var zDT=document.getElementById('TJK_DL').getElementsByTagName('dt');
var zDD=document.getElementById('TJK_DL').getElementsByTagName('dd');
var ToggleON = document.getElementById('TJK_ToggleON');
var ToggleOFF = document.getElementById('TJK_ToggleOFF');
if (ToggleON && ToggleOFF){
ToggleON.onclick = TJK_ToggleDLopen;
ToggleON.title = "Show all answers";
ToggleON.href = "#";
ToggleOFF.onclick = TJK_ToggleDLclose;
ToggleOFF.title = "Hide all answers";
ToggleOFF.href = "#";
}
for(var i=0;i<zDT.length;i++){
var zContent = zDT[i].innerHTML;
var zHref = "<a href='#' onclick="TJK_doToggleDL("+i+");return false" title='Show/hide the answer'>";
zDT[i].innerHTML = zHref + zContent + "</a>";
zDD[i].className='hideDD';
zDT[i].className='DTplus';
}
}
}
TJK_ToggleDL.css
/* "Show All" and "Hide All" links */
#TJK_ToggleON,
#TJK_ToggleOFF {
border: 1px solid #333;
padding: 3px 7px;
margin-right: 5px;
}
/* zeroing out padding and margin */
#TJK_DL dd,
#TJK_DL dt {
margin: 0;
padding: 0;
}
/* margin for the DTs (shorthand) */
#TJK_DL dt {margin:7px 0;}
/* image and left padding for DDs */
#TJK_DL dd {
background: url(answer.gif) no-repeat;
padding-left: 55px;
}
/* styling all anchors in the DTs */
#TJK_DL dt a {
background: 0 50% no-repeat;
padding-left: 32px;
color: #000;
text-decoration: none;
}
#TJK_DL dt a:visited {color: #666}
#TJK_DL dt a:visited:hover,
#TJK_DL dt a:hover,
#TJK_DL dt a:active,
#TJK_DL dt a:focus {font-weight: bold;}
/* the + and - gif in the anchors */
#TJK_DL .DTplus a {background-image: url(toggleDLplus.gif)}
#TJK_DL .DTminus a {background-image: url(toggleDLminus.gif)}
/**********************************/
#TJK_DL .showDD {position: static;}
#TJK_DL dd,
.hideDD {
top: -9999px;
position: absolute;
}
#TJK_ToggleON,
#TJK_ToggleOFF {
display: inline;
cursor: pointer;
cursor: hand;
}
Note that cursor:hand
is for IE5 Win, but this declaration will make this sheet fail Validation. If Validation is important to you, you can either delete this declaration or move it inside a Conditional Comment.
TJK_ToggleDL_ie5mac.css
/**//*/
#TJK_DL .showDD {display: block;}
#TJK_DL dd,
.hideDD {
position: static;
display: none;
}
/**/
For the DOM police
Earlier versions of this script did not use document.write()
, I was using the DOM to plug the stylesheets in the head
element. Unfortunately, setting the rel
attribute of the link
element makes Safari "go blank" and style
fails in IE Win. So, I decided to go with what works!