Jos: Navigation ausschliesslich via DOM erstellen

Hallo.

Mich beschäftigt folgende Aufgabenstellung:

Ich möchte gerne eine Navigationsleiste vollständig mit Javascript erzeugen und über

<script src="Navigation.js" type="text/javascript"></script>

in jede Seite einer Website einbinden.
Die Navigation würde dann (nur einmal erstellt) - immer an derselben Stelle im jedem der Dokumente erscheinen. Der Einsatz von Frames wäre damit umgangen.

Ich möchte bei meiner Lösung gerne möglichst nah am DOM bleiben und würde folgenden Ansatz wählen:

Die erste Funktion erzeugt einen Link-Knoten ("a"), der in eine Ebene ("ebene01") eingehängt wird.
Parameter der Funktion sind das Verweisziel des Links ("ziel")  und der Text des Links ("text") :

function erzeuge_verweis(ziel,text)
{
ebene = document.getElementById('ebene01');
link = document.createElement('a');
link.setAttribute('href',ziel);
link.innerText = text;
ebene.appendChild(link);
}

Um mehrere Links zu erstellen - eine zweite Funktion, die mit 'onload' die Navigation erstellt.

function erzeuge_verweise()
{
erzeuge_verweis('Ziel_1.html','Zur Zielseite 1');
erzeuge_verweis('Ziel_2.html','Zur Zielseite 2');
erzeuge_verweis('Ziel_3.html','Zur Zielseite 3');
}

<body bgcolor="#ffffff" onload="erzeuge_verweise()">

<div id="ebene01"></div>

Frage 1: Mir scheint die Umsetzung noch etwas plump zu sein, insbesondere der Umweg über eine zweite Funktion, um mehrere Links zu erzeugen. Gibt es hier nicht eine elegantere Lösung ?

Frage 2: Mit "setAttribute" kann ich ein Attribut für das Element 'a' definieren. Wie aber muss das ganze aussehen, wenn ich weitere Attribute (z.B. noch eine Klasse)  für das Element 'a' definieren möchte ?

Frage 3: In meinem Konstrukt stehen die Verweise noch nebeneinander, sie sollen aber untereinander erscheinen - es braucht also ein <br> Tag nach jedem Verweis. Wie löse ich das 'Problem' DOM-gerecht und elegant ?

Mfg Jos

  1. Hallo.

    Ich möchte bei meiner Lösung gerne möglichst nah am DOM bleiben und würde folgenden Ansatz wählen:

    function erzeuge_verweis(ziel,text)
    {
    ebene = document.getElementById('ebene01');
    link = document.createElement('a');
    link.setAttribute('href',ziel);
    link.innerText = text;

    innerText hat mit DOM nicht wirklich viel gemein. createTextNode() ist der Aufgabenstellung näher.

    ebene.appendChild(link);
    }

    Um mehrere Links zu erstellen - eine zweite Funktion, die mit 'onload' die Navigation erstellt.

    function erzeuge_verweise()
    {
    erzeuge_verweis('Ziel_1.html','Zur Zielseite 1');
    erzeuge_verweis('Ziel_2.html','Zur Zielseite 2');
    erzeuge_verweis('Ziel_3.html','Zur Zielseite 3');
    }

    <body bgcolor="#ffffff" onload="erzeuge_verweise()">

    <div id="ebene01"></div>

    Frage 1: Mir scheint die Umsetzung noch etwas plump zu sein, insbesondere der Umweg über eine zweite Funktion, um mehrere Links zu erzeugen. Gibt es hier nicht eine elegantere Lösung ?

    Nutze ein Datenfeld und for() || while().

    Frage 2: Mit "setAttribute" kann ich ein Attribut für das Element 'a' definieren. Wie aber muss das ganze aussehen, wenn ich weitere Attribute (z.B. noch eine Klasse)  für das Element 'a' definieren möchte ?

    Vor der Frage stand ich auch schon mal. Gelöst habe ich sie der Einfachheit halber durch .innerHTML, da Mozilla dies auch verarbeitet.

    Frage 3: In meinem Konstrukt stehen die Verweise noch nebeneinander, sie sollen aber untereinander erscheinen - es braucht also ein <br> Tag nach jedem Verweis. Wie löse ich das 'Problem' DOM-gerecht und elegant ?

    function erzeuge_verweis(ziel,text)
       {
       //code für das erzeugen des Verweises

    document.[Element].appendChild(document.createElement('br'))
       }

    Gruß aus Berlin!
    eddi

    1. Hallo eddi.

      Hab' dank für deine Hinweise ... unten das Ergebnis - vielleicht kannst Du mir noch den einen oder anderen Tip geben; Stichwort:'das geht noch eleganter !' ....

      Und zwei ernsthafte Frage hab ich in diesem Zusammenhang leider auch schon wieder:

      Die aufgerufenen Seiten(Zielseite1.html,Zielseite.html,Zielseite3.html) sollen die aktuelle Seite ersetzen, also eine Funktionsweise wie mit

      <a href="javascript:window.location.replace('Zielseite.html')">Linktext</a>

      erreicht werden.

      Meine 1. Frage: wie kann ich das mit dem nachfolgenden Script erreichen ?

      Meine 2. Frage: wie würde man einen Eventhandler (z.B. onmouseover) in einen via DOM erzeugten Link integrieren und diesem Eventhandler eine Funktion zuweisen ?

      <html>
      <head>
      <title></title>
      <script type="text/javascript">
      <!--
      function erzeuge_verweis()
      {
      var ziel = new Array();
      //
      ziel[0] = "Zielseite1.html";
      ziel[1] = "Zielseite2.html";
      ziel[2] = "Zielseite3.html";
      //
      var text = new Array();
      //
      text[0] = "Zielseite 1";
      text[1] = "Zielseite 2";
      text[2] = "Zielseite 3";
      //
      ebene = document.getElementById('ebene01');
      for (i = 0; i < ziel.length; i++)
      {
      link = document.createElement('a');
      link.setAttribute('href',ziel[i]);
      link.appendChild(document.createTextNode(text[i]));
      link.className = "linkeigenschaften";
      ebene.appendChild(link);
      ebene.appendChild(document.createElement('br'))
      }
      }
      //-->
      </script>
      </head>
      <body onload="erzeuge_verweis()">
      <div id="ebene01"></div>
      </body>
      </html>

      Herzlichen Dank nochmals und für eine mögliche weitere Antwort

      Mfg aus Hamburg
      Jos

      1. Hallo Jos.

        <a href="javascript:window.location.replace('Zielseite.html')">Linktext</a>

        Persönlich halte ich das für keine gute Idee, bitte nimm .href, damit der User auch zurück kann.

        Meine 1. Frage: wie kann ich das mit dem nachfolgenden Script erreichen ?

        ziel[0]="javascript:window.location.replace('Zielseite.html')";

        Meine 2. Frage: wie würde man einen Eventhandler (z.B. onmouseover) in einen via DOM erzeugten Link integrieren und diesem Eventhandler eine Funktion zuweisen ?

        Das ist nicht ganz ohne! http://www.javamagazin.de/itr/online_artikel/psecom,id,347,nodeid,11.html - wie im letzten Beitrag von mir gesagt, habe ich darauf durch .innerHTML verzichtet.

        <html>
        <head>
        <title></title>
        <script type="text/javascript">
        <!--
        var ziel = new Array();

        ziel[0] = "Zielseite1.html";
        ziel[1] = "Zielseite2.html";
        ziel[2] = "Zielseite3.html";

        var text = new Array();

        text[0] = "Zielseite 1";
        text[1] = "Zielseite 2";
        text[2] = "Zielseite 3";

        function erzeuge_verweis()
        {
        ebene = document.getElementById('ebene01');
        for (i = 0; i < ziel.length; i++)
        {
        link = document.createElement('a');
        link.setAttribute('href',ziel[i]);
        link.appendChild(document.createTextNode(text[i]));

        link.className = "linkeigenschaften";

        schmeiß das raus und arbeite mit vernünftigen CSS-Angaben (#ebene01 > a)

        ebene.appendChild(link);
        ebene.appendChild(document.createElement('br'))
        }
        }
        //-->
        </script>
        </head>
        <body onload="erzeuge_verweis()">
        <div id="ebene01"></div>
        </body>
        </html>

        Die Frage nach der Eleganz finde ich gut :).

        Wenn Du schon die Seite dynamisch aufbauen willst, mache Dir doch erst einem eine HTML-Layout und erzeuge es komplett dynamisch mit .appendChild(). Verdeutliche Dir wie DOM mit Variablen umgeht und bilde die einzelnen Bausteine in einem polydimensionalen Datenfeld nach. Lade nur noch die einzelnen Variablen mit document.getElementsByTagName("script").src (gegebenenfalls erzeugst Du dieses Element jedesmal neu) und hänge alle Kindknoten ab <body> nach dem Click auf einen Link aus und erzeuge die innere Struktur neu und hänge sie ein.

        Es ist nicht wirklich realistisch, aber möglich UND für meine Begriffe elegant :))))))

        Gruß aus Berlin!
        eddi

        1. Hallo eddi.

          wie im letzten Beitrag von mir gesagt, habe ich darauf durch .innerHTML verzichtet.

          Schade, dass der DOM in einigen Belangen so schwächelt ...

          link.className = "linkeigenschaften";
          schmeiß das raus und arbeite mit vernünftigen CSS-Angaben (#ebene01 > a)

          Das habe ich leider nicht verstanden: dachte, ich hätte die Aufgabe mit den mehreren Attributen mit "className" ELEGANT gelöst .......

          Verdeutliche Dir wie DOM mit Variablen umgeht und bilde die einzelnen Bausteine in einem polydimensionalen Datenfeld nach.

          Du überforderst mich ....

          Bei polydimensionalen Datenfeld stürzt mein Browser immer ab;
          werde die polydimensionalen Datenfelder in einen monotonen Mehrwegstring parsen - auf jeden Fall bin ich dann immer 100% abwärtskompatibel und muß hier keine dummen Fragen mehr posten ;-)

          Vielen Dank und Gruß

          Jos

          1. Hallo eddi.

            link.className = "linkeigenschaften";
            schmeiß das raus und arbeite mit vernünftigen CSS-Angaben (#ebene01 > a)

            Das habe ich leider nicht verstanden: dachte, ich hätte die Aufgabe mit den mehreren Attributen mit "className" ELEGANT gelöst .......

            Um Gottes Willen! Das hast Du auch! Die Fragen, die ich mir bei jeder Zeile JS-Code drei mal stelle:

            1. Ist das wirklich nötig?
            2. Gibt es etwas simpleres?
            3. Wenn schließe ich aus?

            Und da bin ich bei 1. gleich hängengeblieben. (#ebene01 > a) Beschriebt alle Element des Dokuments die ein Link sind und Kindelemente von ELEMENT[id=ebene01] sind. Damit ist das Class ansich überflüssig.
            Aber genaugenommen weiß ich nicht, ob es in Deinem Fall überhaupt sinnvoll ist... (wäre nur mein Weg gewesen ;)
            Als Vergleich, was ich meinte: http://edition-w3c.de/TR/1998/REC-CSS2-19980512/kap05.html#heading-5.1�

            Bei polydimensionalen Datenfeld stürzt mein Browser immer ab;
            werde die polydimensionalen Datenfelder in einen monotonen Mehrwegstring parsen - auf jeden Fall bin ich dann immer 100% abwärtskompatibel und muß hier keine dummen Fragen mehr posten ;-)

            Lass Dich nicht von mir wirre machen, ich mache es im übrigen auch so (sitze grade mal wieder an einem Startmenü für ein CMS eines Kunden)
            Var z sei dabei das Wurzelverzeichnes des Projekts

            var z=new Array()
            z.a-0="name"
            z.a-1="name"
            z.a-1-0="unterverzeichnis"
            z.a-1-2="unterverzeichnis"

            usw.

            Gruß aus Berlin!
            eddi

            1. Hallo eddi.

              dass Du beim Erstellen komplexer Wurzelverzeichnisse nebenbei noch in der Lage bist, komplexe Fragen von Herrn "xy" aus Irgendwo zu beantworten ist prima ...    :-)

              Habe alle Deine Anregungen absorbiert und möchte Dir nicht meine "innerHTML" - Variante vorenthalten. Bin ich dicht dran an der ELEGANTEN Lösung .... , oder geht es noch schlanker ?

              "Es funktioniert ..." macht mich nicht glücklich, es soll perfekt sein ! :-/  :-\  :-/

              -----------------------------------------

              Die Abfrage

              if (i < ziel.length-1)
              ebene.appendChild(document.createElement('br'));

              habe ich deshalb eingefügt, damit nach dem jeweils letzten Link kein <br>-Tag mehr eingefügt wird.

              Müsste es dort nicht eigentlich

              link.appendChild(document.createElement('br'));

              statt

              ebene.appendChild(document.createElement('br'));

              heissen ? Das <br>-Tag wird doch mit "appendChild" genau genommen hinter das letze <span>-Tag gehängt und nicht in den <div>-Bereich (ebene) eingefügt .... ?

              Mfg aus Hamburg Jos

              -----------------------------------------

              <html>
              <head>
              <title></title>
              <script type="text/javascript">
              <!--
              var ziel = new Array();

              ziel[0] = "Zielseite1.html";
              ziel[1] = "Zielseite2.html";
              ziel[2] = "Zielseite3.html";

              var text = new Array();

              text[0] = "Ziel 1";
              text[1] = "Ziel 2";
              text[2] = "Ziel 3";

              function test()
              {
              ebene = document.getElementById('ebene01');

              for (i = 0; i < ziel.length; i++)
              {
              link = document.createElement('span');
              link.innerHTML = "<a href='javascript:window.location.replace(""+ziel[i]+"")'>"+text[i]+"</a>";
              ebene.appendChild(link);
              if (i < ziel.length-1)
              ebene.appendChild(document.createElement('br'));
              }
              }
              //-->
              </script>

              </head>
              <body bgcolor="#ffffff" onload="test()">
              <div id="ebene01"></div>
              </body>
              </html>

              1. Naben Jos.

                "Es funktioniert ..." macht mich nicht glücklich, es soll perfekt sein ! :-/  :-\  :-/

                Dein Wunsch sei mir Befehl:

                Zu bemerken ist: Es gibt keine Eventhandler :)))))))))))

                <html>
                 <head>
                  <title></title>
                  <style type="text/css">
                   #ebene01 {/*notfalls mit width eingrenzen, wegen dem fehlenden br*/}
                   #ebene01 > span {display:block}
                  </style>
                  <script type="text/javascript"><!--
                   var a,ebene,link;
                   var ziel = new Array();

                ziel[0] = "Zielseite1.html*Ziel 1";
                   ziel[1] = "Zielseite2.html*Ziel 2";
                   ziel[2] = "Zielseite3.html*Ziel 3";

                function test()
                    {
                    ebene=document.getElementById('ebene01');
                    for (i=0;i<ziel.length;i++)
                     {
                     text=ziel[i].split("*");

                a=document.createElement('a');
                     a.href="javascript:window.location.replace('"+text[0]+"')";
                     a.appendChild(document.createTextNode(text[1]));

                link=document.createElement('span');
                     link.appendChild(a);

                ebene.appendChild(link);
                     }
                    }//-->
                  </script>
                 </head>
                 <body bgcolor="#ffffff" onLoad="test()">
                  <div id="ebene01"></div>
                 </body>
                </html>

                Gruß aus Berlin nach Hamburg!
                eddi

                1. Tach eddi.

                  Zu bemerken ist: Es gibt keine Eventhandler :)))))))))))

                  Aber jaaaaa .......... steht sogar in meinem Buch !

                  #ebene01 {/*notfalls mit width eingrenzen, wegen dem fehlenden br*/}

                  Trixer !!! ;-)

                  text=ziel[i].split("*");

                  Trixer !!! ;-)

                  a=document.createElement('a');
                       a.href="javascript:window.location.replace('"+text[0]+"')";
                       a.appendChild(document.createTextNode(text[1]));

                  Pfiffig, wird übernommen !

                  Na, dann herzlichen Dank für den angenehmen Dialog, ich könnte ewig so weitermachen ... bis zum nächsten Mal zu einem anderen Thema !

                  Grüße nach Berlin

                  Jos

                  1. Hallo Jos,

                    #ebene01 {/*notfalls mit width eingrenzen, wegen dem fehlenden br*/}

                    Trixer !!! ;-)

                    der eigentliche Tick liegt aber in

                    #ebene01 > span {display:block}

                    begraben, dadurch wird das document.createElement('br'); überflüssig

                    text=ziel[i].split("*");

                    Trixer !!! ;-)

                    Das macht sich erst nach dem vierten Link bezahlt und spart Traffic ;)

                    Gruß aus Berlin!
                    eddi

          2. Anmerkung für Archivnutzer:

            wie im letzten Beitrag von mir gesagt, habe ich darauf durch .innerHTML verzichtet.

            Schade, dass der DOM in einigen Belangen so schwächelt ...

            Unter [pref:t=83227&m=486064] wird dargelegt, wie dies doch bewerkstelligt werden kann