Et skjelett
Det første vi gjør er å etablere et skjelett av en webside som har en menybeskrivelse,
et utseende og en grunnleggende dynamikk. Vårt første eksempel
har begrenset funksjonalitet på den måten at det eneste resultatet av våre valg er at vi
får se menyteksten som nytt innhold i framvisningsfeltet.
Menyen
Selve menyen er beskrevet slik:
<div id="menuRoot" class="menuRoot">
<div id="Menu-0">
<div id="Menu-1">
<div id="Menu-2"></div>
<div id="Menu-3"></div>
</div>
<div id="Menu-4"></div>
</div>
<div id="Menu-5">
<div id="Menu-6">
<div id="Menu-7"></div>
<div id="Menu-8"></div>
</div>
</div>
</div>
Altså ingen style-attributter og ingen Javaskript, verken kall eller definisjoner.
Stilsettet
Stilsettet er ikke veldig gjennomarbeidet og
har ikke stort annen funksjon enn å vise nivå på
menyene som indentering.
/* banner, footer and content*/
.banner{font-size:36px;text-align:center;border-bottom:solid}
.footer{font-size:18px;text-align:center;border-top:solid}
#content{margin-left:20px}
/*menues*/
#menuRoot{border-right:solid;float:left;padding:20px;width:150px}
#menuRoot div{cursor:pointer;margin-left:5px;font-weight:bold}
#menuRoot div div{cursor:pointer;margin-left:15px;font-weight:normal}
#menuRoot div div div{cursor:pointer;margin-left:25px;font-weight:normal}
.hidden{display:none}
.hilited{display:block;color:red}
.normal{display:block;color:black}
Javaskriptet
Gitt dette utgangspunktet må Javaskriptet gjøre tre ting:
- Etablere kopling mellom struktur og stilsettet (class)
- Etablere kopling mellom strukturen og Javaskriptet (onclick etc.)
- Respondere på brukerbegivenheter
Det to første oppgavene må gjøres når siden etableres, f.eks. onload().
Denne delen kan se slik ut:
function initPage()
{
// prepare menu with contents and onclick
var menuhead=document.getElementById(menuRootId);
var level=0;
var mList=menuhead.getElementsByTagName('div');
for (var ix=0;ix<mList.length;ix++)
{
var menuitem=mList[ix];
var menuitemid=menuitem.id;
txtNode=document.createTextNode(menuitemid)
if(menuitem.firstChild)
menuitem.insertBefore(txtNode,menuitem.firstChild);
else
menuitem.appendChild(txtNode);
menuitem.onclick=handleClick;
if(menuitem.captureEvents)
menuitem.captureEvents(Event.CLICK);
}
// select the first in top level as a start selection
selectMenu(mList[0].id);
}
Koden refererer noen metoder og konstanter som ikke er definert i denne funksjonen.
Det totale scriptet, med funksjonene:
showMenu(), showChildren(), findMenuItem(), hideAllMenues(),
selectMenu(), handleClick() og initPage() ser slik ut:
var menuRootId="menuRoot";
var hiddenkey=0;
var normalkey=1;
var hilitedkey=2;
function showMenu(menuitem,classkey)
{
if(classkey==hiddenkey)
menuitem.className='hidden';
else if(classkey==normalkey)
menuitem.className='normal';
else if(classkey==hilitedkey)
menuitem.className='hilited';
else
alert('what, unknown classkey ?'+classkey);
}
function showChildren(rootNode,key)
{
if(rootNode)
{
var clist=rootNode.childNodes;
for(var ix=0;ix<clist.length;ix++)
if(clist[ix].nodeName.toLowerCase()=='div')
showMenu(clist[ix],key);
}
else
alert('what, no root ?');
}
function findMenuItem(root,targetId)
{
var list=root.childNodes;
if(!list)
return false;
for(var ix=0;ix<list.length;ix++)
{
if(list[ix].nodeName.toLowerCase()=='div')
{
var menuItem=list[ix];
var menuId=menuItem.id;
if(targetId==menuId)
{
// expand self and all siblings
showChildren(menuItem.parentNode,normalkey);
//expand all children
showChildren(menuItem,normalkey);
return true;
}
else
{
var foundIt= findMenuItem(menuItem,targetId);
if(foundIt)
{
// expand all siblings
showChildren(menuItem.parentNode,normalkey);
return true;
}
}
}
}
return false;
}
function hideAllMenues(root)
{
var mList=root.getElementsByTagName('div');
for (var ix=0;ix<mList.length;ix++)
showMenu(mList[ix],hiddenkey);
}
function selectMenu(targetId)
{
var menuhead=document.getElementById(menuRootId);
hideAllMenues(menuhead);
findMenuItem(menuhead,targetId);
showMenu(document.getElementById(targetId),hilitedkey);
div=document.getElementById('content');
div.innerHTML=targetId;
}
function handleClick(e)
{
if(!e)
var e=window.event;
var targ=null;
if (e.target)
targ = e.target;
else if (e.srcElement)
targ = e.srcElement;
if (targ.nodeType == 3) // Safari bug
targ = targ.parentNode;
var targetId=targ.id;
selectMenu(targetId);
e.cancelBubble = true;
if (e.stopPropagation)
e.stopPropagation();
}
//initpage
function initPage()
{
// prepare menu with contents and onclick
var menuhead=document.getElementById(menuRootId);
var level=0;
var mList=menuhead.getElementsByTagName('div');
for (var ix=0;ix<mList.length;ix++)
{
var menuitem=mList[ix];
var menuitemid=menuitem.id;
txtNode=document.createTextNode(menuitemid)
if(menuitem.firstChild)
menuitem.insertBefore(txtNode,menuitem.firstChild);
else
menuitem.appendChild(txtNode);
menuitem.onclick=handleClick;
if(menuitem.captureEvents)
menuitem.captureEvents(Event.CLICK);
}
// select the first in top level as a start selection
selectMenu(mList[0].id);
}
//eofinitpage
En funksjonell løsning
Logikken er den samme som i skjelettet, men vi har utvidet
funksjonaliteten slik at en menyvalg fører til at vi henter
innhold via en ajax-forespørsel.
Det vi mangler er to ting:
- Kopling mellom menyelementet og den addressen vi skal bruke i ajax-forespørselen
- Ajax forespørselen og resulatthandteringen
Det første, koplingen mellom menylinje og adresse, kan vi realisere på mange måter.
En måte er å legge inn følgende oppslagstabell på siden :
// menuids (text) to urls
var menuAccess=new Array();
menuAccess[0]=['Velkommen','my-ajax-0.html'];
menuAccess[1]=['Blid', 'my-ajax-1.html'];
menuAccess[2]=['Sur', 'my-ajax-2.html'];
menuAccess[3]=['Forvirret', 'my-ajax-7.html'];
menuAccess[4]=['Skjegget', 'my-ajax-4.html'];
menuAccess[5]=['Irritert', 'my-ajax-5.html'];
menuAccess[6]=['Skeptisk', 'my-ajax-6.html'];
menuAccess[7]=['Surprise','my-ajax-8.html'];
function getUrl(menuid)
{
for(var ix=0;ix<menuAccess.length;ix++)
{
if(menuAccess[ix][0]==menuid)
return menuAccess[ix][1];
}
return menuAccess[0][1];
}
Selve koplingn mot Ajax gjør vi ved hjelp av
jQuery
[1]
som ajax-bibliotek.
Det komplette Javascriptbiblioteket blir nå slik:
// relies on jquery
var menuRootId="menuRoot";
var hiddenkey=0;
var normalkey=1;
var hilitedkey=2;
function showMenu(menuitem,classkey)
{
if(classkey==hiddenkey)
menuitem.className='hidden';
else if(classkey==normalkey)
menuitem.className='normal';
else if(classkey==hilitedkey)
menuitem.className='hilited';
else
alert(classkey);
}
function showChildren(rootNode,key)
{
if(rootNode)
{
var clist=rootNode.childNodes;
for(var ix=0;ix<clist.length;ix++)
if(clist[ix].nodeName.toLowerCase()=='div')
showMenu(clist[ix],key);
}
else
alert('no root');
}
function findMenuItem(root,targetId)
{
var list=root.childNodes;
if(!list)
return false;
for(var ix=0;ix<list.length;ix++)
{
if(list[ix].nodeName.toLowerCase()=='div')
{
var menuItem=list[ix];
var menuId=menuItem.id;
if(targetId==menuId)
{
// expand self and all siblings
showChildren(menuItem.parentNode,normalkey);
//expand all children
showChildren(menuItem,normalkey);
return true;
}
else
{
var foundIt= findMenuItem(menuItem,targetId);
if(foundIt)
{
// expand all siblings
showChildren(menuItem.parentNode,normalkey);
return true;
}
}
}
}
return false;
}
function hideAllMenues(root)
{
var mList=root.getElementsByTagName('div');
for (var ix=0;ix<mList.length;ix++)
showMenu(mList[ix],hiddenkey);
}
function selectMenu(targetId)
{
var menuhead=document.getElementById(menuRootId);
hideAllMenues(menuhead);
findMenuItem(menuhead,targetId);
showMenu(document.getElementById(targetId),hilitedkey);
// get the url and do ajax-request by jquery
var url=getUrl(targetId);
$('#content').load(url);
}
function handleClick(e)
{
if(!e)
var e=window.event;
var targ=null;
if (e.target)
targ = e.target;
else if (e.srcElement)
targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;
var targetId=targ.id;
selectMenu(targetId);
e.cancelBubble = true;
if (e.stopPropagation)
e.stopPropagation();
}
function initPage()
{
// prepare menu with contents and onclick
var menuhead=document.getElementById(menuRootId);
var level=0;
var mList=menuhead.getElementsByTagName('div');
for (var ix=0;ix<mList.length;ix++)
{
var menuitem=mList[ix];
var menuitemid=menuitem.id;
var homeadr=document.location;
txtNode=document.createTextNode(menuitemid)
if(menuitem.firstChild)
menuitem.insertBefore(txtNode,menuitem.firstChild);
else
menuitem.appendChild(txtNode);
menuitem.onclick=handleClick;
if(menuitem.captureEvents) menuitem.captureEvents(Event.CLICK);
}
// select the first in top level
selectMenu(mList[0].id);
}