Menü mit Submenüs benutzbar/praktikabel machen

acquire

Mitglied
Hallo zusammen,

mein CSS-Menü darf nur aus <ul> und <li>-Tags bestehen.
Mein Menü sieht als Liste so aus:
* Startseite
* Infoseite A
o Info1
o Info2
o Info3
* Infoseite B
o Info1
o Info2
o Info3
o Info4
o Info5
o Info6
o Info7
o Info8
o Info9
* Impressum
Da die ganzen Seiten mit den o's einklappen, sobald man nicht mehr auf sie oder dem Parent mit dem Mauscurser zeigt, kann man nicht angenehm zwischen den einzelnen Parents wechseln, da ständig das Menü auseinander gerissen wird. In diesem Beispiel funktioniert es noch, im HTML Beispiel (folgend) nicht mehr.

Hier meine HTML-Datei:
HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>

<style type="text/css">
#MenuNav, #MenuNav ul {
	list-style-image:url('li.gif');
	margin:0;
	padding-left:20px;
	width:170px;
	_width:190px;
	overflow:hidden;
}

#MenuNav li ul {
	list-style-image:url('lili.gif');
	padding-left:39px;
	_padding-left:34px; /*IE6 Hack*/
	display:none;
}

#MenuNav li ul ul {
	display:none;
}

#MenuNav li a:hover {
}

#MenuNav li:hover ul ul,
#MenuNav li:hover ul ul ul,
#MenuNav li.sfhover ul ul,
#MenuNav li.sfhover ul ul ul {
display:none;
}

#MenuNav li:hover ul,
#MenuNav li.sfhover ul,
#MenuNav li li:hover ul,
#MenuNav li li.sfhover ul,
#MenuNav li li li:hover ul,
#MenuNav li li li.sfhover ul {
display:block;
}

#MenuNav UL UL LI {
list-style-image:url('lili.gif');
}
</style>
</head>
<body>


<ul id="MenuNav">

<li><a href="http://www.google.de/">Startseite</a></li>

<li><a href="http://www.google.de/">Infoseite A</a>
<ul>
<li><a href="http://www.google.de/">Info1</a></li>
<li><a href="http://www.google.de/">Info2</a></li>
<li><a href="http://www.google.de/">Info3</a></li>
</ul>
</li>

<li><a href="http://www.google.de/">Infoseite B</a>
<ul>
<li><a href="http://www.google.de/">Info1</a></li>
<li><a href="http://www.google.de/">Info2</a></li>
<li><a href="http://www.google.de/">Info3</a></li>
<li><a href="http://www.google.de/">Info4</a></li>
<li><a href="http://www.google.de/">Info5</a></li>
<li><a href="http://www.google.de/">Info6</a></li>
<li><a href="http://www.google.de/">Info7</a></li>
<li><a href="http://www.google.de/">Info8</a></li>
<li><a href="http://www.google.de/">Info9</a></li>
<li><a href="http://www.google.de/">Info10</a></li>
<li><a href="http://www.google.de/">Info20</a></li>
<li><a href="http://www.google.de/">Info30</a></li>
<li><a href="http://www.google.de/">Info40</a></li>
<li><a href="http://www.google.de/">Info50</a></li>
<li><a href="http://www.google.de/">Info60</a></li>
<li><a href="http://www.google.de/">Info70</a></li>
<li><a href="http://www.google.de/">Info80</a></li>
<li><a href="http://www.google.de/">Info90</a></li>
</ul>
</li>

<li><a href="http://www.google.de/">Infoseite C</a></li>

<li><a href="http://www.google.de/">Infoseite D</a>
<ul>
<li><a href="http://www.google.de/">Info1</a></li>
<li><a href="http://www.google.de/">Info2</a></li>
<li><a href="http://www.google.de/">Info3</a></li>
</ul>
</li>

<li><a href="http://www.google.de/">Impressum</a></li>
</ul>

</body>
</html>
Kopiert am besten den Quelltext und testet dann die HTML-Datei, dann wisst ihr was ich meine.


==

Wie kann ich mit CSS (oder JavaScript) es schaffen, dass die Aufgeklappten Submenüs erst nach einiger Zeit wieder zuklappen oder erst zuklappen, wenn man aus dem Menü raus ist mit dem Zeiger und das nächste Submenü öffnet, welches dann offen bleibt und das andere Submenü einklappt?

Bei Javascript-Lösungen müsste es ähnlich wie die Suckerfish-Methode implementierbar sein.
Mein Haupt-<ul> hat die ID" MenuNav", die lis folgend i.d.R. die gleiche ID+eine fortlaufende Nummer.


Ich bin über jede Anregung die Bedienbarkeit des Menüs zu verbessers erfreut. Wichtig ist jedoch, dass ich nur Listenelemente zur Verfügung habe und CSS (eventuell auch JavaScript).


Gruß, acquire
 
Vielen Dank Sven für den Link und das zur Verfügungstellen deines Werkes.

Dazu habe ich eine Frage:
Code:
        //Layer für das  Menu
    objMenu             = document.getElementById('menu');
enthält doch die ID des DIV-Tags, oder?
 
Mittlerweile klappt das meiste wunderbar mit dem JavaScript Treeview.

Mein Problem besteht nun darin, dass ich die ul und li Punkte nicht mehr via CSS anpassen kann.

Kurz gefasst:
Mir fehlt
- Ergänzung des JS, sodass wenn eine Oberpunktseite geöffnet ist, die Level 1 Kinder angezeigt werden
- Beschränkung, dass nur die obersten li-Punkte eine bestimmte Grafik erhalten, alle anderen eine andere (auch gerne durch CSS-Formatierung)

Der von mir bisher angepasste tree.js Quelltext:
Code:
   /** Ein paar Variablen */

        //Layer für das  Menu
    objMenu             = document.getElementById('menu');

        //Dateityp Icons
    strIcoType          = '.gif';

        //Icon-Verzeichnis: Wichtig: Vollständiger Pfad
    strIcoDir           = 'menuimages/';;

        //Grafikname für Datei
    strFile             = 'li';

        //Zweig + Vertikale Linie + Ordner
    strSpace1           = 'space1'; // Bildatei transparent mit 1x1px Größe

        //Space
    strSpace            = 'space';

        //Icons zum Expandieren/kollabieren
    arrFolderEntries    = new Array('lili', 'minus');

        //Zielfenster zum ermitteln des aktuellen Menupunktes
    objTargetWindow     = 'self';

        //GET-Parameter beim Ermitteln des aktuellen Links ignorieren
    blnIgnoreQuery      = false;

        //Anker beim Ermitteln des aktuellen Links ignorieren
    blnIgnoreAnchor     = true;

        //Display-Eigenschaften für Menupunkte
    arrDisplay=new Array('none','inline');

        //nur 1 Ordner offen lassen?
    blnToggle=0;





    arrTree=new Array();


    /** ist objImg eine Schaltfläche zum kollabieren/expandieren */

    function is_entry(objImg)
    {
        return(objImg.tagName == 'IMG' && objImg.name == 'entry')
    }


    /** Ausgabe img-Code für strSrc */

    function img_html(strSrc, blnFunction)
    {
        strFunction = (blnFunction)
                        ? 'onclick="expand(this.parentNode);return false"'
                        : '';

        return('<img src="' + strIcoDir
                            + strSrc
                            + strIcoType
                            + '"border="0"align="top"' + strFunction + '>');
    }



    function expand(obj)
    {

    intEvent = (obj.lastChild.style.display == 'none'
                || expand.arguments.length > 1) ? 1 : 0;

    arrRegExp=new Array();
    arrRegExp.push(new RegExp(arrFolderEntries[1]));
    arrRegExp.push(new RegExp(arrFolderEntries[0]));





    for(d=0;d<obj.parentNode.childNodes.length;++d)
    {

      oDim=obj.parentNode.childNodes[d];
      blnEvt=(oDim==obj)?intEvent:0
      if(!blnToggle && oDim!=obj)continue;
      if(oDim.lastChild.tagName=='UL')oDim.lastChild.style.display=arrDisplay[blnEvt];


      for(i=0;i<oDim.childNodes.length;++i)
        {
          ice_setpm(oDim.childNodes[i],blnEvt);
        }
      }
    }


    /** "Parsen" der Listeneinträge und erzeugen der Baumstruktur */

    function build_tree()
    {
        if( arrTree.length <= intDimension)
            {
            arrTree.push(strSpace1);
            }

        strIco = (!is_file(objItem)) ? strSpace1 : strFile;
        strTree = '<br>';
        strEntry = (!is_file(objItem)) ? arrFolderEntries[0] : strSpace1;
       /** strEntry += (is_end()) ? '' : '';*/

        for (v = 0; v < intDimension; ++v)
            {
            strTree+=img_html(arrTree[v]);
            }

        objItem.innerHTML = strTree
                            + img_html(strEntry,!is_file(objItem))
                            + img_html(strIco)+objItem.innerHTML;

        if (!is_file(objItem))
            {
            arrTree[intDimension] = 'space';
           /** if (is_end(objItem))
                {
                arrTree[intDimension] = 'space';
                }*/
            }
        }


    /**
      * Dimensionen > 1 verstecken und
      * Listen-Eigenschaften entfernen
      **/

    function collapse_menu()
    {
        objItem.style.listStyleType = 'none';
        objItem.style.display = 'inline';
        objItem.style.padding = 0;
        objItem.parentNode.style.display = (get_dimension(objItem) == 0)
                                                ? 'inline'
                                                : 'none';

    }

    /** Befindet sich Objekt innerhalb des Menues */

    function in_menu(obj)
    {
    objParentNode = obj.parentNode;
    while(objParentNode != objMenu && objParentNode.tagName != 'BODY')
        {
        objParentNode = objParentNode.parentNode;
        }
    return(objParentNode == objMenu);
    }


    /** Enthält objekt eine UL-Liste */
    function is_file()
    {
    return(!objItem.hasChildNodes()||objItem.lastChild.tagName!='UL')
    }


    function get_dimension()
    {
        intDimension=-1;
        objParentNode=objItem.parentNode;
        while(objParentNode!=objMenu)
            {
            if(objParentNode.tagName=='UL'){intDimension++;}
            objParentNode=objParentNode.parentNode;
            }
        return intDimension;
    }

    function is_end()
    {
    (objItem.parentNode.lastChild.tagName);
    return(objItem==objItem.parentNode.lastChild);
    }


    function strip_spaces(str)
    {
    strOut=str.replace(/>\s+</gm,'><');
    strOut=str.replace(/>\s+/gm,'>');
    strOut=str.replace(/\s+</gm,'<');
    return strOut;
    }
    /** Durchlaufen alle Li-Elemente */


    function init_menu()
    {
    if (!document.getElementsByTagName
        || typeof document.getElementsByTagName('html')[0].innerHTML != 'string')
        {
        return;
        }

    objMenu.innerHTML = strip_spaces(objMenu.innerHTML);

    for (l = 0; l < document.getElementsByTagName('li').length; ++l)
            {
            objItem = document.getElementsByTagName('li')[l];

            if (in_menu(objItem))
                {
                intDimension = get_dimension(objItem);
                collapse_menu(objItem);
                build_tree(objItem);
                }
            }
    objMenu.innerHTML = strip_spaces(objMenu.innerHTML);
    opening();
    }


    /** Aktuellen Link ermitteln und Menu epandieren */

    function opening()
    {

    for(a = 0; a < document.links.length; ++a)
        {
        if (in_menu(document.links[a]))
            {

            document.links[a].style.textDecoration = 'none';
            objFolder = document.links[a].parentNode;

            if (is_active_link(document.links[a].href))
                {
                while(objFolder.parentNode != objMenu && objFolder.parentNode.tagName!='BODY')
                    {
                    if(objFolder.tagName == 'UL')
                        {
                        expand(objFolder.parentNode,1);
                        document.links[a].style.fontWeight = 'bold';
                        }

                    objFolder=objFolder.parentNode;
                    }
                }
            }
        }
    }


    /** Prüfen zweier Links auf Übereinstimmung */

    function is_active_link(strUrl)
    {
        arrUrls = new Array(strUrl,String(eval(objTargetWindow + '.location')));

        for(u = 0; u < arrUrls.length; ++u)
            {
            if (blnIgnoreAnchor)
                {
                arrUrls[u] = arrUrls[u].replace(/#.*?$/, '');
                }

            if (blnIgnoreQuery)
                {
                arrUrls[u]=arrUrls[u].replace(/\?[^#]*/g, '');
                }
            }

        return(arrUrls[0]==arrUrls[1]);
    }

    function ice_setpm(img,e)
    {
      arrRegExp=[new RegExp(arrFolderEntries[1]),new RegExp(arrFolderEntries[0])];
        if(is_entry(img))
            {
            img.src=String(img.src).replace(arrRegExp[e],arrFolderEntries[e]);

            img.nextSibling.src =strIcoDir + strSpace1 + strIcoType;
            }
    }

    /**
      * ce_all:
      * kollabiert/expandiert das komplette Menu
      * Parameter:
      * kollabieren:0
      * expandieren:1
      */

    function ce_all(e)
    {
        for(i=1;i<objMenu.getElementsByTagName('UL').length;++i)
          {
            objMenu.getElementsByTagName('UL')[i].style.display=arrDisplay[e];
          }
         for(i=0;i<objMenu.getElementsByTagName('IMG').length;++i)
          {
            if(objMenu.getElementsByTagName('IMG')[i].name=="entry")
              {
                 ice_setpm(objMenu.getElementsByTagName('IMG')[i],e);
              }
          }

    }

    /**
      * Starten des Ganzen...kann optional auch per Body-Onload erfolgen,
      * auf jeden Fall erst im Anschluss an das Laden des Menu-Elements
      */


    init_menu();

Mein Problem ist, dass ich mit JavaScript bis zu diesem Menü nie etwas zu tun hatte.
Ich bin für jede Art der Hilfestellung dankbar!
 
Das Thema hat sich erledig, nun funktioniert das Menü wie gewünscht.
Nochmals meinen Dank an Sven Mintel für sein Entgegenkommen.

Die auf meine Bedürfnisse angepasste Version (falls jemand mal das gleiche benötigt wie ich) - bitte bedenken, dass der Code nicht optimiert ist, sondern nur angepasst, sodass die Ausgabe stimmt - :
Code:
   /** Ein paar Variablen */

        //Layer für das  Menu
    objMenu             = document.getElementById('menu');

        //Dateityp Icons
    strIcoType          = '.gif';

        //Icon-Verzeichnis: Wichtig: Vollständiger Pfad
    strIcoDir           = 'images/';

        //Grafikname für Unterpunkt
    strFile             = 'li';

        //Grafikname für Oberpunkt
    strFile2             = 'lili';

        //Spacer in Grafikgröße
    strSpace1           = 'space1';

        //Space
    strSpace            = 'space';

        //Zielfenster zum ermitteln des aktuellen Menupunktes
    objTargetWindow     = 'self';

        //GET-Parameter beim Ermitteln des aktuellen Links ignorieren
    blnIgnoreQuery      = false;

        //Anker beim Ermitteln des aktuellen Links ignorieren
    blnIgnoreAnchor     = true;

        //Display-Eigenschaften für Menupunkte
    arrDisplay=new Array('none','inline');

        //nur 1 Ordner offen lassen?
    blnToggle=1;





    arrTree=new Array();


    /** ist objImg eine Schaltfläche zum kollabieren/expandieren */

    function is_entry(objImg)
    {
        return(objImg.tagName == 'IMG' && objImg.name == 'entry')//;
    }


    /** Ausgabe img-Code für strSrc */

    function img_html(strSrc, blnFunction)
    {
        strFunction = (blnFunction)
                        ? 'onclick="expand(this.parentNode);return false"'
                        : '';

        return('<img src="' + strIcoDir
                            + strSrc
                            + strIcoType
                            + '"border="0"align="top"' + strFunction + '>');
    }



    function expand(obj)
    {

    intEvent = (obj.lastChild.style.display == 'none'
                || expand.arguments.length > 1) ? 1 : 0;

    for(d=0;d<obj.parentNode.childNodes.length;++d)
    {

      oDim=obj.parentNode.childNodes[d];
      blnEvt=(oDim==obj)?intEvent:0
      if(!blnToggle && oDim!=obj)continue;
      if(oDim.lastChild.tagName=='UL')oDim.lastChild.style.display=arrDisplay[blnEvt];
      }
    }


    /** "Parsen" der Listeneinträge und erzeugen der Baumstruktur */

    function build_tree()
    {
        if( arrTree.length <= intDimension)
            {
            arrTree.push(strSpace1);
            }

       if (intDimension >= 1) {
        strIco = (!is_file(objItem)) ? strSpace1 : strFile2;
        strTree = '<br>';
        strEntry = (!is_file(objItem)) ? strFile2 : strSpace1;
       }
       else
       {
       strIco = (!is_file(objItem)) ? strSpace1 : strFile;
        strTree = '<br>';
        strEntry = (!is_file(objItem)) ? strFile : strSpace1;
      }

        for (v = 0; v < intDimension; ++v)
            {
            strTree+=img_html(arrTree[v]);
            }

        objItem.innerHTML = strTree
                            + img_html(strEntry,!is_file(objItem))
                            + img_html(strIco)+objItem.innerHTML;

        if (!is_file(objItem))
            {
            arrTree[intDimension] = 'space';
            }

        }


    /**
      * Dimensionen > 1 verstecken und
      * Listen-Eigenschaften entfernen
      **/

    function collapse_menu()
    {
        objItem.style.listStyleType = 'none';
        objItem.style.display = 'inline';
        objItem.style.padding = 0;
        objItem.parentNode.style.display = (get_dimension(objItem) == 0)
                                                ? 'inline'
                                                : 'none';

    }

    /** Befindet sich Objekt innerhalb des Menues */

    function in_menu(obj)
    {
    objParentNode = obj.parentNode;
    while(objParentNode != objMenu && objParentNode.tagName != 'BODY')
        {
        objParentNode = objParentNode.parentNode;
        }
    return(objParentNode == objMenu);
    }


    /** Enthält objekt eine UL-Liste */
    function is_file()
    {
    return(!objItem.hasChildNodes()||objItem.lastChild.tagName!='UL')
    }


    function get_dimension()
    {
        intDimension=-1;
        objParentNode=objItem.parentNode;
        while(objParentNode!=objMenu)
            {
            if(objParentNode.tagName=='UL'){intDimension++;}
            objParentNode=objParentNode.parentNode;
            }
        return intDimension;
    }

    function is_end()
    {
    (objItem.parentNode.lastChild.tagName);
    return(objItem==objItem.parentNode.lastChild);
    }


    function strip_spaces(str)
    {
    strOut=str.replace(/>\s+</gm,'><');
    strOut=str.replace(/>\s+/gm,'>');
    strOut=str.replace(/\s+</gm,'<');
    return strOut;
    }
    /** Durchlaufen alle Li-Elemente */


    function init_menu()
    {
    if (!document.getElementsByTagName
        || typeof document.getElementsByTagName('html')[0].innerHTML != 'string')
        {
        return;
        }

    objMenu.innerHTML = strip_spaces(objMenu.innerHTML);

    for (l = 0; l < document.getElementsByTagName('li').length; ++l)
            {
            objItem = document.getElementsByTagName('li')[l];

            if (in_menu(objItem))
                {
                intDimension = get_dimension(objItem);
                collapse_menu(objItem);
                build_tree(objItem);
                }
            }
    objMenu.innerHTML = strip_spaces(objMenu.innerHTML);
    opening();
    }


    /** Aktuellen Link ermitteln und Menu epandieren */

    function opening()
    {

    for(a = 0; a < document.links.length; ++a)
        {
        if (in_menu(document.links[a]))
            { if(document.links[a].parentNode.getElementsByTagName('UL').length)document.links[a].onclick=function(){expand(this.parentNode);}

            document.links[a].style.textDecoration = 'none';
            objFolder = document.links[a].parentNode;

            if (is_active_link(document.links[a].href))
                {
                while(objFolder.parentNode != objMenu && objFolder.parentNode.tagName!='BODY')
                    {
                    if(objFolder.tagName == 'UL')
                        {
                        expand(objFolder.parentNode,1);
                        document.links[a].style.fontWeight = 'bold';
                        }
                    objFolder=objFolder.parentNode;
                    }
                expand(document.getElementsByTagName('li')[a]);
            }
        }
    }


    /** Prüfen zweier Links auf Übereinstimmung */

    function is_active_link(strUrl)
    {
        arrUrls = new Array(strUrl,String(eval(objTargetWindow + '.location')));

        for(u = 0; u < arrUrls.length; ++u)
            {
            if (blnIgnoreAnchor)
                {
                arrUrls[u] = arrUrls[u].replace(/#.*?$/, '');
                }

            if (blnIgnoreQuery)
                {
                arrUrls[u]=arrUrls[u].replace(/\?[^#]*/g, '');
                }
            }

        return(arrUrls[0]==arrUrls[1]);
    }

    /**
      * Starten des Ganzen...kann optional auch per Body-Onload erfolgen,
      * auf jeden Fall erst im Anschluss an das Laden des Menu-Elements
      */


    init_menu();


Edit:
Wie ich feststellen musste funktioniert expand(document.getElementsByTagName('li')[a]); (Aufklappen der Kinder bei Aufruf der Seite) bei einigen CMS-Sytemen nicht, waum auch immer.


Nachfolgend sämtliche Änderungen, damit beim Klicken auf einen Link eventuelle Kinder ausgeklappt werden (damit hatte ich bisher keine Probleme):


Im Skript folgende Passage suchen:
Code:
    function opening()
    {

    for(a = 0; a < document.links.length; ++a)
        {
        if (in_menu(document.links[a]))
            {
            
            document.links[a].style.textDecoration = 'none';

Und wie folgt ändern:
Code:
    function opening()
    {

    for(a = 0; a < document.links.length; ++a)
        {
        if (in_menu(document.links[a]))
            {
          if(document.links[a].parentNode.getElementsByTagName('UL').length)document.links[a].onclick=function(){expand(this.parentNode);}
            document.links[a].style.textDecoration = 'none';

Suche nun:
Code:
            if (is_active_link(document.links[a].href))
                {
                while(objFolder.parentNode != objMenu && objFolder.parentNode.tagName!='BODY')
                    {
                    if(objFolder.tagName == 'UL')
                        {
                        expand(objFolder.parentNode,1);
                        document.links[a].style.fontWeight = 'bold';
                        }
					objFolder=objFolder.parentNode;
                    }
                }
und ändere es ab in folgendes:
Code:
            if (is_active_link(document.links[a].href))
                {
                expand(objFolder);
                while(objFolder.parentNode != objMenu && objFolder.parentNode.tagName!='BODY')
                    {
                    if(objFolder.tagName == 'UL')
                        {
                        expand(objFolder.parentNode,1);
                        document.links[a].style.fontWeight = 'bold';
                        }
					objFolder=objFolder.parentNode;
                    }
                }
Fertig.
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück