mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
499 lines
20 KiB
HTML
499 lines
20 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<!--
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=418368
|
|
-->
|
|
<head>
|
|
<title>nsIHyperLinkAccessible chrome tests</title>
|
|
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
|
|
|
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
|
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
|
|
|
<script type="application/javascript">
|
|
var gAccRetrieval = null;
|
|
|
|
function testThis(aID, aAcc, aRole, aAnchors, aName, aValid, aStartIndex,
|
|
aEndIndex)
|
|
{
|
|
is(aAcc.finalRole, aRole, "Wrong role for ID " + aID + "!");
|
|
is(aAcc.anchorCount, aAnchors, "Wrong number of anchors for ID "
|
|
+ aID + "!");
|
|
is(aAcc.getAnchor(0).name, aName, "Wrong name for ID "
|
|
+ aID + "!");
|
|
is(aAcc.valid, aValid, "No correct valid state for ID "
|
|
+ aID + "!");
|
|
is(aAcc.startIndex, aStartIndex, "Wrong startIndex value for ID "
|
|
+ aID + "!");
|
|
is(aAcc.endIndex, aEndIndex, "Wrong endIndex value for ID "
|
|
+ aID + "!");
|
|
}
|
|
|
|
function testFocus(aID, aAcc, aSelectedBefore, aSelectedAfter)
|
|
{
|
|
is(aAcc.selected, aSelectedBefore,
|
|
"Wrong selected state before focus for ID " + aID + "!");
|
|
document.getElementById(aID).focus();
|
|
is(aAcc.selected, aSelectedAfter,
|
|
"Wrong seleccted state after focus for ID " + aID + "!");
|
|
}
|
|
|
|
function testStates(aID, aAcc, aState, aExtraState, aAbsentState,
|
|
aShowStateDebugFlag)
|
|
{
|
|
var state = {}, extraState = {};
|
|
aAcc.getFinalState(state, extraState);
|
|
|
|
if (aShowStateDebugFlag) {
|
|
var list = gAccRetrieval.getStringStates(state.value, 0);
|
|
|
|
var str = "";
|
|
for (var i = 0; i < list.length; i++)
|
|
str += list.item(i) + "\n";
|
|
|
|
alert(str);
|
|
}
|
|
|
|
is(state.value & aState, aState, "Wrong state bits for ID " + aID + "!");
|
|
is(extraState.value & aExtraState, aExtraState,
|
|
"Wrong extra state bits for ID " + aID + "!");
|
|
if (aAbsentState != 0)
|
|
is(state.value & aAbsentState, 0, "state bits should not be present in ID "
|
|
+ aID + "!");
|
|
}
|
|
|
|
function testAction(aId, aAcc, aActionName)
|
|
{
|
|
var numActions = aActionName ? 1 : 0;
|
|
is(aAcc.numActions, numActions,
|
|
"Wrong actions number for ID " + aId);
|
|
try {
|
|
is(aAcc.getActionName(0), aActionName,
|
|
"Wrong action name for ID " + aId);
|
|
} catch (e) {
|
|
if (numActions)
|
|
ok(false, "Exception on action name getting for ID " + aId);
|
|
else
|
|
ok(true, "Correct action name for ID " + aId);
|
|
}
|
|
}
|
|
|
|
function doTest()
|
|
{
|
|
// Mapping needed state flags for easier handling.
|
|
const state_focusable =
|
|
Components.interfaces.nsIAccessibleStates.STATE_FOCUSABLE;
|
|
const state_focused =
|
|
Components.interfaces.nsIAccessibleStates.STATE_FOCUSED;
|
|
const state_selectable =
|
|
Components.interfaces.nsIAccessibleStates.STATE_SELECTABLE;
|
|
const state_linked =
|
|
Components.interfaces.nsIAccessibleStates.STATE_LINKED;
|
|
const state_traversed =
|
|
Components.interfaces.nsIAccessibleStates.STATE_TRAVERSED;
|
|
|
|
const ext_state_multi_line =
|
|
Components.interfaces.nsIAccessibleStates.EXT_STATE_MULTI_LINE;
|
|
const ext_state_horizontal =
|
|
Components.interfaces.nsIAccessibleStates.EXT_STATE_HORIZONTAL;
|
|
const ext_state_required =
|
|
Components.interfaces.nsIAccessibleStates.STATE_REQUIRED;
|
|
const ext_state_invalid =
|
|
Components.interfaces.nsIAccessibleStates.STATE_INVALID;
|
|
|
|
gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
|
|
getService(Components.interfaces.nsIAccessibleRetrieval);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// normal hyperlink
|
|
var normalHyperlinkElement = document.getElementById("NormalHyperlink");
|
|
var normalHyperlinkAcc;
|
|
try {
|
|
normalHyperlinkAcc = gAccRetrieval.getAccessibleFor(normalHyperlinkElement).
|
|
QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch(e) {
|
|
ok(normalHyperlinkAcc, "no interface for normal hyperlink!");
|
|
}
|
|
testThis("NormalHyperlink", normalHyperlinkAcc,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
|
|
"Mozilla Foundation", true, 18, 19);
|
|
is(normalHyperlinkAcc.getURI(0).spec, "http://www.mozilla.org/",
|
|
"URI wrong for normalHyperlinkElement!");
|
|
testStates("NormalHyperlink", normalHyperlinkAcc,
|
|
(state_focusable | state_linked),
|
|
(ext_state_horizontal), (0));
|
|
testFocus("NormalHyperlink", normalHyperlinkAcc, false, true);
|
|
testStates("NormalHyperlink", normalHyperlinkAcc,
|
|
(state_focusable | state_focused | state_linked),
|
|
(ext_state_horizontal), (0));
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// ARIA hyperlink
|
|
var ariaHyperlinkElement = document.getElementById("AriaHyperlink");
|
|
var ariaHyperlinkAcc;
|
|
try {
|
|
ariaHyperlinkAcc = gAccRetrieval.getAccessibleFor(ariaHyperlinkElement).
|
|
QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch(e) {
|
|
ok(ariaHyperlinkAcc, "no interface for ARIA Hyperlink!");
|
|
}
|
|
testThis("AriaHyperlink", ariaHyperlinkAcc,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
|
|
"Mozilla Foundation Home", true, 32, 33);
|
|
testStates("AriaHyperlink", ariaHyperlinkAcc,
|
|
(state_focusable | state_linked),
|
|
(ext_state_horizontal), (0));
|
|
testFocus("AriaHyperlink", ariaHyperlinkAcc, false, true);
|
|
testStates("AriaHyperlink", ariaHyperlinkAcc,
|
|
(state_focusable | state_focused | state_linked),
|
|
(ext_state_horizontal), (0));
|
|
testAction("AriaHyperlink", ariaHyperlinkAcc, "click");
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// ARIA hyperlink with status invalid
|
|
var invalidAriaHyperlinkElement =
|
|
document.getElementById("InvalidAriaHyperlink");
|
|
var invalidAriaHyperlinkAcc;
|
|
try {
|
|
invalidAriaHyperlinkAcc =
|
|
gAccRetrieval.getAccessibleFor(invalidAriaHyperlinkElement).
|
|
QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch(e) {
|
|
ok(invalidAriaHyperlinkAcc, "no interface for invalid ARIA hyperlink!");
|
|
}
|
|
is(invalidAriaHyperlinkAcc.valid, false, "Should not be valid!");
|
|
testStates("InvalidAriaHyperlink", invalidAriaHyperlinkAcc,
|
|
(state_linked),
|
|
(ext_state_horizontal), (state_focusable));
|
|
testFocus("InvalidAriaHyperlink", invalidAriaHyperlinkAcc,
|
|
false, false);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// image map and its link children
|
|
var imageMapHyperlinkElement =
|
|
document.getElementById("imgmap");
|
|
var imageMapHyperlinkAcc;
|
|
try {
|
|
imageMapHyperlinkAcc =
|
|
gAccRetrieval.getAccessibleFor(imageMapHyperlinkElement).
|
|
QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch(e) {
|
|
ok(imageMapHyperlinkAcc, "no Image Map interface!");
|
|
}
|
|
testThis("imgmap", imageMapHyperlinkAcc,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_IMAGE_MAP, 2,
|
|
"b", true, 83, 84);
|
|
is(imageMapHyperlinkAcc.getURI(0).spec,
|
|
"http://www.bbc.co.uk/radio4/atoz/index.shtml#b", "URI wrong!");
|
|
is(imageMapHyperlinkAcc.getURI(1).spec,
|
|
"http://www.bbc.co.uk/radio4/atoz/index.shtml#a", "URI wrong!");
|
|
testStates("imgmap", imageMapHyperlinkAcc,
|
|
(0),
|
|
(ext_state_horizontal), (0));
|
|
|
|
var area1 = imageMapHyperlinkAcc.firstChild;
|
|
ok(area1, "no children in image map acc!");
|
|
var area1HL;
|
|
try {
|
|
area1HL =
|
|
area1.QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch (e) {
|
|
ok(area1HL, "no interface for first child of Image Map!");
|
|
}
|
|
testThis("Area1", area1HL,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
|
|
"b", true, 0, 1);
|
|
is(area1HL.getURI(0).spec,
|
|
"http://www.bbc.co.uk/radio4/atoz/index.shtml#b", "URI wrong!");
|
|
testStates("Area1", area1HL,
|
|
(state_linked),
|
|
(0), (0));
|
|
|
|
var area2 = area1.nextSibling;
|
|
ok(area2, "no next sibling!");
|
|
var area2HL;
|
|
try {
|
|
area2HL =
|
|
area2.QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch (e) {
|
|
ok(area2HL, "no interface for second child of Image Map!");
|
|
}
|
|
testThis("Area2", area2HL,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
|
|
"a", true, 1, 2);
|
|
is(area2HL.getURI(0).spec,
|
|
"http://www.bbc.co.uk/radio4/atoz/index.shtml#a", "URI wrong!");
|
|
testStates("Area2", area2HL,
|
|
(state_linked),
|
|
(0), (0));
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// empty hyperlink
|
|
var emptyLinkElement = document.getElementById("emptyLink");
|
|
var EmptyHLAcc;
|
|
try {
|
|
EmptyHLAcc =
|
|
gAccRetrieval.getAccessibleFor(emptyLinkElement).
|
|
QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch (e) {
|
|
ok(EmptyHLAcc, "no interface for empty link!");
|
|
}
|
|
testThis("emptyLink", EmptyHLAcc,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
|
|
null, true, 98, 99);
|
|
testStates("emptyLink", EmptyHLAcc,
|
|
(state_focusable | state_linked),
|
|
(ext_state_horizontal), (0));
|
|
testAction("emptyLink", EmptyHLAcc, "jump");
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// normal hyperlink with embedded span
|
|
var hyperlinkElementWithSpan = document.getElementById("LinkWithSpan");
|
|
var hyperlinkWithSpanAcc;
|
|
try {
|
|
hyperlinkWithSpanAcc =
|
|
gAccRetrieval.getAccessibleFor(hyperlinkElementWithSpan).
|
|
QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch(e) {
|
|
ok(hyperlinkWithSpanAcc, "no interface for hyperlink with span!");
|
|
}
|
|
testThis("LinkWithSpan", hyperlinkWithSpanAcc,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
|
|
"Heise Online", true, 124, 125);
|
|
is(hyperlinkWithSpanAcc.getURI(0).spec, "http://www.heise.de/",
|
|
"URI wrong for hyperlinkElementWithSpan!");
|
|
testStates("LinkWithSpan", hyperlinkWithSpanAcc,
|
|
(state_focusable | state_linked),
|
|
(ext_state_horizontal), (0));
|
|
testFocus("LinkWithSpan", hyperlinkWithSpanAcc, false, true);
|
|
testStates("LinkWithSpan", hyperlinkWithSpanAcc,
|
|
(state_focusable | state_focused | state_linked),
|
|
(ext_state_horizontal), (0));
|
|
testAction("LinkWithSpan", hyperlinkWithSpanAcc, "jump");
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Named anchor, should never have state_linked
|
|
var namedAnchorElement = document.getElementById("namedAnchor");
|
|
var namedAnchorAcc;
|
|
try {
|
|
namedAnchorAcc = gAccRetrieval.getAccessibleFor(namedAnchorElement).
|
|
QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch(e) {
|
|
ok(namedAnchorAcc, "no interface for named anchor!");
|
|
}
|
|
testThis("namedAnchor", namedAnchorAcc,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
|
|
"This should never be of state_linked", true, 202, 203);
|
|
testStates("namedAnchor", namedAnchorAcc,
|
|
(state_selectable),
|
|
(ext_state_horizontal), (state_focusable | state_linked));
|
|
testAction("namedAnchor", namedAnchorAcc, "");
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// No link (hasn't any attribute), should never have state_linked
|
|
var noLinkElement = document.getElementById("noLink");
|
|
var noLinkAcc;
|
|
try {
|
|
noLinkAcc = gAccRetrieval.getAccessibleFor(noLinkElement).
|
|
QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch(e) {
|
|
ok(noLinkAcc, "no interface for named anchor!");
|
|
}
|
|
testThis("noLink", noLinkAcc,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
|
|
"This should never be of state_linked", true, 262, 263);
|
|
testStates("noLink", noLinkAcc,
|
|
0,
|
|
(ext_state_horizontal), (state_focusable | state_linked));
|
|
testAction("noLink", noLinkAcc, "");
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Link with registered 'click' event, should have state_linked
|
|
var linkWithClickElement = document.getElementById("linkWithClick");
|
|
var linkWithClickAcc;
|
|
try {
|
|
linkWithClickAcc = gAccRetrieval.getAccessibleFor(linkWithClickElement).
|
|
QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch(e) {
|
|
ok(linkWithClickAcc, "no interface for named anchor!");
|
|
}
|
|
testThis("linkWithClick", linkWithClickAcc,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
|
|
"This should have state_linked", true, 301, 302);
|
|
testStates("linkWithClick", linkWithClickAcc,
|
|
(state_linked),
|
|
(ext_state_horizontal), 0);
|
|
testAction("linkWithClick", linkWithClickAcc, "click");
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Maps to group links (bug 431615).
|
|
var linksMapElement = document.getElementById("linksmap");
|
|
var linksMapAcc;
|
|
try {
|
|
linksMapAcc = gAccRetrieval.getAccessibleFor(linksMapElement);
|
|
} catch(e) { }
|
|
|
|
ok(linksMapAcc, "no accessible for map grouping links!");
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Link with title attribute, no name from the subtree (bug 438325).
|
|
var id = "linkWithTitleNoNameFromSubtree";
|
|
var linkElement = document.getElementById(id);
|
|
var linkAcc;
|
|
try {
|
|
linkAcc = gAccRetrieval.getAccessibleFor(linkElement).
|
|
QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch(e) {
|
|
ok(linkAcc, "no interface for link with ID " + id + "!");
|
|
}
|
|
testThis(id, linkAcc,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
|
|
"Link with title", true, 354, 355);
|
|
testStates(id, linkAcc,
|
|
(state_linked),
|
|
(ext_state_horizontal), 0);
|
|
testAction(id, linkAcc, "jump");
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Link with title attribute, name from the subtree - onsreen name
|
|
// (bug 438325).
|
|
id = "linkWithTitleNameFromSubtree";
|
|
linkElement = document.getElementById(id);
|
|
linkAcc;
|
|
try {
|
|
linkAcc = gAccRetrieval.getAccessibleFor(linkElement).
|
|
QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch(e) {
|
|
ok(linkAcc, "no interface for link with ID " + id + "!");
|
|
}
|
|
testThis(id, linkAcc,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
|
|
"the name from subtree", true, 403, 404);
|
|
testStates(id, linkAcc,
|
|
(state_linked),
|
|
(ext_state_horizontal), 0);
|
|
testAction(id, linkAcc, "jump");
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Link with title attribute, name from the nested html:img (bug 438325).
|
|
id = "linkWithTitleNameFromImg";
|
|
linkElement = document.getElementById(id);
|
|
linkAcc;
|
|
try {
|
|
linkAcc = gAccRetrieval.getAccessibleFor(linkElement).
|
|
QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch(e) {
|
|
ok(linkAcc, "no interface for link with ID " + id + "!");
|
|
}
|
|
testThis(id, linkAcc,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
|
|
"The title for link", true, 458, 459);
|
|
testStates(id, linkAcc,
|
|
(state_linked),
|
|
(ext_state_horizontal), 0);
|
|
testAction(id, linkAcc, "jump");
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Link with label, no name from the subtree (bug 438325).
|
|
id = "linkWithLabelNoNameFromSubtree";
|
|
linkElement = document.getElementById(id);
|
|
linkAcc;
|
|
try {
|
|
linkAcc = gAccRetrieval.getAccessibleFor(linkElement).
|
|
QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
|
|
} catch(e) {
|
|
ok(linkAcc, "no interface for link with ID " + id + "!");
|
|
}
|
|
testThis(id, linkAcc,
|
|
Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
|
|
"Link with label and nested image:", true, 462, 463);
|
|
testStates(id, linkAcc,
|
|
(state_linked),
|
|
(ext_state_horizontal), 0);
|
|
testAction(id, linkAcc, "jump");
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
SimpleTest.finish();
|
|
}
|
|
|
|
SimpleTest.waitForExplicitFinish();
|
|
addLoadEvent(doTest);
|
|
</script>
|
|
</head>
|
|
<body>
|
|
|
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418368">Mozilla Bug 418368</a>
|
|
<p id="display"></p>
|
|
<div id="content" style="display: none"></div>
|
|
<pre id="test">
|
|
</pre>
|
|
|
|
<br>Simple link:<br>
|
|
<a id="NormalHyperlink" href="http://www.mozilla.org">Mozilla Foundation</a>
|
|
<br>ARIA link:<br>
|
|
<span id="AriaHyperlink" role="link"
|
|
onclick="window.open('http://www.mozilla.org/');"
|
|
tabindex="0">Mozilla Foundation Home</span>
|
|
<br>Invalid, non-focusable hyperlink:<br>
|
|
<span id="InvalidAriaHyperlink" role="link" aria-invalid="true"
|
|
onclick="window.open('http:/www.mozilla.org/');">Invalid link</span>
|
|
<br>Image map:<br>
|
|
<map name="atoz_map">
|
|
<area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#b"
|
|
coords="17,0,30,14"
|
|
alt="b"
|
|
shape="rect"></area>
|
|
<area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#a"
|
|
coords="0,0,13,14"
|
|
alt="a"
|
|
shape="rect"></area>
|
|
</map>
|
|
<img width="447" id="imgmap"
|
|
height="15"
|
|
usemap="#atoz_map"
|
|
src="http://www.bbc.co.uk/radio4/images/letters.gif"></img>
|
|
|
|
<br>Empty link:<br>
|
|
<a id="emptyLink" href=""><img src=""></img></a>
|
|
|
|
<br>Link with embedded span<br>
|
|
<a id="LinkWithSpan" href="http://www.heise.de/"><span lang="de">Heise Online</span></a>
|
|
|
|
<br>Named anchor, must not have "linked" state for it to be exposed correctly:<br>
|
|
<a id="namedAnchor" name="named_anchor">This should never be of state_linked</a>
|
|
|
|
<br>Link having no attributes, must not have "linked" state:</br>
|
|
<a id="noLink">This should never be of state_linked</a>
|
|
|
|
<br>Link with registered 'click' event: </br>
|
|
<a id="linkWithClick" onclick="var clicked = true;">This should have state_linked</a>
|
|
|
|
<br>Link with title attribute (no name from subtree): </br>
|
|
<a id="linkWithTitleNoNameFromSubtree" href="http://www.heise.de/"
|
|
title="Link with title"><img src=""/></a>
|
|
|
|
<br>Link with title attribute (name from subtree): </br>
|
|
<a id="linkWithTitleNameFromSubtree" href="http://www.heise.de/"
|
|
title="Link with title">the name from subtree</a>
|
|
|
|
<br>Link with title attribute (name from nested image): </br>
|
|
<a id="linkWithTitleNameFromImg" href="http://www.heise.de/"
|
|
title="Link with title"><img src="" alt="The title for link"/></a>
|
|
|
|
<br><label for="linkWithLabelNoNameFromSubtree">Link with label and nested image: </label></br>
|
|
<a id="linkWithLabelNoNameFromSubtree"
|
|
href="http://www.heise.de/"><img src=""/></a>
|
|
|
|
<br>Map that is used to group links (www.w3.org/TR/WCAG10-HTML-TECHS/#group-bypass),
|
|
also see the bug 431615:<br>
|
|
<map id="linksmap" title="Site navigation">
|
|
<ul>
|
|
<li><a href="http://mozilla.org">About the project</a></li>
|
|
<li><a href="http://mozilla.org">Sites and sounds</a></li>
|
|
</ul>
|
|
</map>
|
|
|
|
</body>
|
|
</html>
|