Showing posts with label collapsible. Show all posts
Showing posts with label collapsible. Show all posts

Sunday, September 26, 2010

Creating a vertical navigation bar with collapsible sections

1. Set up the JavaScript. Create a new JavaScript document and attach it to the HTML
file via a script element in the head of the document. (In the example files, this
document has been named vertical-navigation-bar.js.) First, add the
JavaScript lines first shown in the “Enhancing accessibility for collapsible content”
section:
var cssNode = document.createElement('link');
cssNode.setAttribute('rel', 'stylesheet');
cssNode.setAttribute('type', 'text/css');
cssNode.setAttribute('href', 'javascript-overrides.css');
document.getElementsByTagName('head')[0].appendChild(cssNode);
Next, add the toggler script shown in the “Modularizing the collapsible content
script” section, but amend the target element as shown:
function toggle(toggler) {
if(document.getElementById) {
targetElement = toggler.nextSibling;
if(targetElement.className == undefined) {
targetElement = toggler.nextSibling.nextSibling;
}
if (targetElement.style.display == "block")
{
targetElement.style.display = "none";
}
else
{
targetElement.style.display = "block";
}
}
}

2. Amend the list. To each top-level navigation link, add the onclick attribute, as
shown following. And to each second-level list that you initially want to be invisible,
add the class attribute shown. For any list you want to be visible, instead add
style="display: block;".
<li>
<a href="#" onclick="toggle(this); return false;">Section one</a>
<ul class="collapsibleList">
<li><a href="#">A link to a page</a></li>
<li><a href="#">A link to a page</a></li>
<li><a href="#">A link to a page</a></li>
<li><a href="#">A link to a page</a></li>
</ul>
</li>

3.
Add a style sheet. Create and save the style sheet document javascriptoverrides.
css, and add the following rule to initially hide any lists with the
collapsibleList class value in JavaScript-enabled browsers.
#navigation ul.collapsibleList {
display: none;
}
The following images show the results (which depict, from left to right, the
default, hover, and active states).

How to find targets for collapsible content scripts

If you want to change your document structure when using the script from the previous
section in this chapter, you need to find the parent/sibling path, in Internet Explorer and in
other browsers. If you’ve a good grasp of JavaScript, this should be simple; however, if you
don’t—or you just want to sanity-check your values—it’s simple to find out what an element’s
parent is, what it’s next sibling is, and various combinations thereof.
First, give your clickable element a unique id value:
<p><a id="linkToggler" href="#" title="Toggle section"
å onclick="toggle(this); return false;">Toggle div 1!</a></p>
Elsewhere within the web page, add the following script:
<script type="text/javascript">
//<![CDATA[
alert(document.getElementById("linkToggler").nodeName);
//]]>
</script>
Before .nodeName, add whatever combination of .parentNode and .nextSibling you
like—here’s an example:
<script type="text/javascript">
//<![CDATA[
alert(document.getElementById("linkToggler").parentNode.
ånextSibling.nextSibling.nodeName);
//]]>
</script>
When you load the web page in a browser, an alert message will be displayed. This will
detail what the target element is, based on the path defined in the previous code block.

Modularizing the collapsible content script

Although the previous script works perfectly well for a single div, it’s awkward if you want
to use several divs over the course of a page. That’s how the old Images from Iceland site
works, and I had to keep track of id names and values while constructing it. However, it is
possible to make a toggler strip more modular, although this relies on keeping document
structure very strict as far as the collapsible sections go. The files for this section are in the
collapsible-div-modular folder within the chapter 5 folder.
The JavaScript is similar to that in the previous example.
function toggle(toggler) {
if(document.getElementById) {
targetElement = toggler.parentNode.nextSibling;
if(targetElement.className == undefined) {
targetElement = toggler.parentNode.nextSibling.nextSibling;
}
if (targetElement.style.display == "block") {
targetElement.style.display = "none";
}
else {
targetElement.style.display = "block";
}
}
}
The main change is that instead of targeting a div with a specific id value, the script
targets an element in relation to the one being used as a toggler, by way of the
parentNode/nextSibling JavaScript properties.
If you look at the HTML document, you’ll see that the parent of the anchor element is the
p element. What the next sibling element is depends on the browser—Internet Explorer
just looks for the next element in the document (div), but other browsers count whitespace
as the next sibling.
<p><a href="#" title="Toggle section" onclick="toggle(this); return
å false;">Toggle div 1!</a></p>
<div class="expandable">
<p>Initially hidden content (div 1) goes here.</p>
</div>
It would be possible to get around this by stripping whitespace. However, a line in the
JavaScript makes this unnecessary.
if(document.getElementById) {
targetElement = toggler.parentNode.nextSibling;
if(targetElement.className == undefined) {
targetElement = toggler.parentNode.nextSibling.nextSibling;
}
The first line of the previous code block sets the target to the next sibling of the parent
element of the link. In Internet Explorer this works, but other browsers find only whitespace.
Therefore, the second line essentially says, “If you find whitespace (undefined),
then set the target to the next sibling on.” It’s a bit of a workaround, but it’s only one line
of JavaScript.
The JavaScript also includes the method used in the preceding “Enhancing accessibility for
collapsible content” section, to make the togglable sections initially invisible in JavaScriptenabled
browsers only. Note that the related CSS is slightly different to that shown in the
previous section—instead of hidden content being in a div with an id value of hiddenDiv,
it’s now in multiple divs, all of which have a class value of expandable. Therefore, the
selector in the CSS rule has been updated accordingly:
.expandable {
display: none;
}
This system enables you to use as many collapsible divs as you like on the page, and you
don’t have to set id values—the toggling is essentially automated. However, as mentioned
earlier, you must ensure that your structure remains the same for each area that can be
toggled, otherwise the script won’t find the correct element to make visible or invisible
when the links are clicked.

Enhancing accessibility for collapsible content

Although the old version of the Images from Iceland site looks good, it has a problem in
common with the previous exercise: when JavaScript is disabled, the initially hidden content
is inaccessible. The Iceland site was quickly knocked together a number of years back
and has been superseded with a new site, but for any site developed today, there should
be no excuses.
In the previous exercise, the hidden content is set to be hidden by default and the display
property is toggled via the JavaScript function. What therefore needs to be done is to
make the content visible by default and then override this, making it invisible, but only if the user has JavaScript. The first thing to do is remove the style attribute from the following
line of code:
<div id="hiddenDiv" style="display: none;">
Next, a style sheet is created (named javascript-overrides.css for this example), with a
rule that targets the relevant div and sets display to none.
#hiddenDiv {
display: none;
}
Finally, amendments are made to the JavaScript file, adding some lines that attach the new
JavaScript document to the web page:
var cssNode = document.createElement('link');
cssNode.setAttribute('rel', 'stylesheet');
cssNode.setAttribute('type', 'text/css');
cssNode.setAttribute('href', 'javascript-overrides.css');
document.getElementsByTagName('head')[0].appendChild(cssNode);
The results of this are the following:
If a user has JavaScript enabled, javascript-overrides.css is loaded, applying the
display value of none to the togglable div.
If a user has JavaScript disabled, javascript-overrides.css is not loaded, meaning
the togglable div contents are visible.
See the collapsible-div-accessible folder within the chapter 5 folder for reference
files.

Collapsible page content : Setting up a collapsible div

1. Examine the script. Open collapsible-div.js. The code enables you to target any
div with a unique id value. Each time the script is run, it determines whether the
display value of the div is set to block (which makes it visible). If it is, the value is
set to none, thereby making it invisible. If it isn’t set to block (which means it’s set
to none), the script sets the value to block.
function swap(targetId){
if (document.getElementById)
{
target = document.getElementById(targetId);
if (target.style.display == "block")
{
target.style.display = "none";
}
else
{
target.style.display = "block";
}
}
}

2. Add a link. Add the code block shown following—when clicked, the link will toggle
the hidden content. The value within the onclick attribute (hiddenDiv, in this
case) is the id value of the div that this link will toggle.
<p><a href="#" title="Toggle section" onclick="toggleDiv('hiddenDiv');
å return false;">Toggle div!</o>

3. Add a div, and give it an id value equal to the onclick value from the previous
step. Within the div, add whatever content you want. The style attribute makes
the div initially hidden.
<p><a href="#" title="Toggle section" onclick="toggleDiv('hiddenDiv');
å return false;">Toggle div!</a></p>
<div id="hiddenDiv" style="display: none;">
<p>Initially hidden content goes here.</p>
</div>