Teil von SELFHTML aktuell Teil von Artikel Teil von Dynamisches HTML

Andreas Zierhut
Positionierung von Layern (DHTML)

nach unten Andreas Zierhut
nach unten Voraussetzungen
nach unten Problemstellung
nach unten Vorüberlegungen
nach unten Lösung 1: Koordinaten anhand eines relativ positionierten Layers
nach unten Lösung 2: Koordinaten anhand von Ankern/Bildern
nach unten Anwendung: a:hover im Netscape Navigator

Andreas Zierhut

E-Mail: E-Mail Andreas.Zierhut@t-online.de
Homepage-URL: deutschsprachige Seite http://www.t-online.de/home/andreas.zierhut/

Bei Fragen zu diesem Beitrag bitte den Autor des Beitrags kontaktieren!

nach obennach unten

Voraussetzungen

Begriff DHTML
Wenn HTML dynamisch geändert wird, spricht man von Seite D(ynamic) HTML . Beim Ändern von Elementen eines Dokumentes spielen fast immer Layer eine Rolle, da der Netscape Navigator 4 nur beschränkten Zugriff auf die Eigenschaften von Elementen hat und somit z. B. keine Schriftfarben durch Neusetzen einer Eigenschaft (Seite color) ändern kann.

Begriff Layer
Ein Layer ist eine Ebene/Schicht in einem HTML-Dokument. Eine normale Seite liegt auf der 1. Ebene, Layer können durch den Seite z-Index einer Ebene zugeordnet werden.

Erstellen eines Layers:

Für Netscape Navigator und Internet Explorer:

<div id="DerLayer" style="position: absolute; z-Index: 2;">
  Layerinhalt
</div>

Netscape Navigator spezifisch:

<layer name="DerLayer" z-index=2>
  Layerinhalt
</layer>

Der Layer steht in der 2. Schicht, d. h. der Inhalt des Dokuments würde an der Stelle verdeckt.
Die 2. Variante ist vorzuziehen, wenn der Layer mit dem JavaScript-Befehl Seite document.write() in das Dokument geschrieben wird und eine Lösung speziell für den Netscape Navigator geschrieben werden soll. Bei der 1. Variante neigt der Netscape Navigator sonst zu Abstürzen.

nach obennach unten

Problemstellung

Oftmals wäre es hilfreich, wenn ein Layer, also eine Schicht/Ebene, im Dokument platziert werden könnte.
Ein konkretes Beispiel: eine Menüleiste soll in einer variablen Tabelle in der zweiten Zeile angezeigt werden. Eine Seite absolute Positionierung kommt aus Gründen der unterschiedlichen Darstellung bei verschiedenen Bildschirmauflösungen nicht in Frage.

Aussehen einer Menüleiste (Beispiel):

1. Spalte
2. Spalte
Untermenü

nach obennach unten

Vorüberlegungen

Warum nicht einfach einen relativ positionierten Layer verwenden?
In CSS gibt es die Möglichkeit mit Seite position: relative einen Layer mitten im Dokument einzufügen.

Nachteile:

Wenn es darum geht, die Schriftfarbe beim Überfahren mit der Maus zu ändern, scheidet diese Lösung aus. Die Farbe kann im Netscape Navigator nicht geändert werden, es muß der komplette Inhalt eines Layers neu geschrieben werden.

Fazit: Ein absolut positionierter Layer erleichtert vieles.

nach obennach unten

Lösung 1: Koordinaten anhand eines relativ positionierten Layers

Prinzip: die Stelle im Dokument mit einem relativ positioniertem Layer markieren, anschließend einen absolut positionierten an dieselbe Position setzen.

Popup-Seite Anzeigebeispiel: So sieht's aus

Beispiel:

<html>
<head>

<script language="JavaScript1.2" type="text/javascript">
<!--

var ie = document.all ? true : false;
var ns = document.layers ? true : false;

function mark()
{
  if (ie)
    document.write('<div id="DerLayer">&nbsp;</div>');
  else if (ns)
    document.write('<ilayer name="DerLayer">&nbsp;</ilayer>');
}

function ShowNew()
{
  if (ie) {
    var derlayer = document.all.DerLayer;
    var anzlayer = document.all.AnzeigeLayer;
    anzlayer.style.posLeft = getLeft(derlayer);
    anzlayer.style.posTop = getTop(derlayer);
    anzlayer.style.visibility = 'visible';
  }
  else if (ns) {
    var derlayer = document.DerLayer;
    var anzlayer = document.AnzeigeLayer;
    anzlayer.pageX = derlayer.pageX;
    anzlayer.pageY = derlayer.pageY;
    anzlayer.visibility = 'show';
  }
}
function getLeft(l)
{
  if (l.offsetParent) return (l.offsetLeft + getLeft(l.offsetParent));
  else return (l.offsetLeft);
}
function getTop(l)
{
  if (l.offsetParent) return (l.offsetTop + getTop(l.offsetParent));
  else return (l.offsetTop);
}
function Write(name, inhalt)
{
  if (ie)
    document.all[name].innerText = inhalt;
  else if (ns) {
    with (document[name].document) {
      open();
      write(inhalt);
      close();
    }
  }
}

//-->
</script>

</head>
<body onLoad="ShowNew()">

<div id="AnzeigeLayer" style="position: absolute; visibility: hidden">Layerinhalt</div>

<table border=1 cellspacing=0 cellpadding=0 width="100%">
  <tr>
    <td width="20%">&nbsp;</td>
    <td width="80%">
      <script language="JavaScript1.2" type="text/javascript">
      <!--
        mark();
      //-->
      </script>
    </td>
  </tr>
</table>

<a href="javascript:Write('AnzeigeLayer', 'Neuer Inhalt')">Neuer Inhalt</a>

</body>
</html>

Beschreibung:

Das Script merkt sich die Position in der Tabelle und setzt nach dem Laden der Seite einen neuen Layer an die Stelle.
Hier wird also der Text "Layerinhalt" in der 2. Spalte der Tabelle angezeigt.
Bei Klick auf den Link wird ändert sich der Text zu "Neuer Inhalt".

Funktion mark():
Mit document.write() wird ein relativ positionierter Layer ins Dokument eingefügt.

Funktion ShowNew():
Der AnzeigeLayer wird an die Position des vorher eingefügten Layers positioniert und angezeigt.

Funktionen getLeft() und getTop():
Im Internet Explorer gibt es keine Eigenschaften, die die Bildschirmkoordinaten eines Objekts speichern. Um die Koordinaten zu ermitteln, müssen alle X und Y-Werte der Elternelemente ( Seite offsetParent) aufaddiert werden.

Funktion Write(name, inhalt):
Der Inhalt des AnzeigeLayer wird dynamisch geändert. Die Funktion hätte bei Anwendung auf den relativ positionierten Layer (DerLayer) im Netscape Navigator keine Auswirkung.

nach obennach unten

Lösung 2: Koordinaten anhand von Ankern/Bildern

Prinzip: Positionen mit einem Seite Anker oder einem Seite Bild versehen und die Eigenschaften "x" und "y" bzw. Seite offsetLeft und Seite offsetTop lesen.

Popup-Seite Anzeigebeispiel: So sieht's aus

Beispiel:

<html>
<head>

<script language="JavaScript1.2" type="text/javascript">
<!--

var ie = document.all ? true : false;
var ns = document.layers ? true : false;

var aktuell = 0;
var anzahl = 4;
function MoveLayer()
{
  if (++aktuell == anzahl) aktuell = 1;

  if (ns) {

    var pos = document.anchors['Position'+aktuell];
    if (!pos)
      pos = document.images['Position'+aktuell];

    with (document.DerLayer) {
      pageX = pos.x;
      pageY = pos.y;
      visibility = 'show';
    }
  }
  else if (ie) {

    var pos = document.all['Position'+aktuell];
    with (document.all.DerLayer.style) {
      posLeft = getLeft(pos);
      posTop = getTop(pos);
      visibility = 'visible';
    }

  }
}
function getLeft(l)
{
  if (l.offsetParent) return (l.offsetLeft + getLeft(l.offsetParent));
  else return (l.offsetLeft);
}
function getTop(l)
{
  if (l.offsetParent) return (l.offsetTop + getTop(l.offsetParent));
  else return (l.offsetTop);
}
//-->
</script>

</head>
<body onLoad="MoveLayer()">

<div id="DerLayer" style="position: absolute; visibility: hidden">Inhalt</div>

<table border=1 cellspacing=0 cellpadding=0 width="100%">
  <tr>
    <td width="10%"><a name="Position1">&nbsp;</a></td>
    <td width="50%"><img src="spacer.gif" width=1 height=1 name="Position2" alt=""></td>
    <td width="40%">&nbsp;<br>
                    <a name="Position3">&nbsp;</a></td>
  </tr>
</table>

<a href="javascript:MoveLayer()">Zur n&auml;chsten Position</a>

</body>
</html>

Beschreibung:

Es werden 3 Stellen im Dokument mittels Bildern und Ankern markiert. Beim Laden des Dokuments wird der Layer an der Position1 (Anker) angezeigt, beim Drücken auf den Link wird er an die jeweils nächste Position verschoben.
Diese Lösung ist die gefährlichere. Unter gewissen Umständen funktioniert es nicht, da die Eigenschaften "x" und "y" nur die relative Position zum Elternelement beinhalten.

Funktion MoveLayer():
Es wird ermittelt, ob die nächste Position mit einem Anker oder einem Bild bestimmt wurde. Anschließend wird der Layer an die Stelle des Ankers/Bildes geschoben und angezeigt.

Funktionen getLeft() und getTop():
Selbes Prinzip wie bei der Lösung 1.

nach obennach unten

Anwendung: a:hover im Netscape Navigator

Eine schmerzvolle Erfahrung für viele Webdesigner: der Teil von CSS-Befehl Seite a:hover funktioniert nicht im Netscape Navigator.
Eine allgemeine Lösung für dieses Problem gibt es nicht. Meine Idee war, ein möglichst kurzes und pflegeleichtes Script zu schaffen, das zumindest einen vergleichbaren Ersatz darstellt.
Die Idee: jeder Link hat eine Eigenschaft "x" und "y", womit die Koordinaten des Links zumindest in 90% aller Fälle zuverlässig bestimmt werden können. Der Text des Links steht in der Eigenschaft "text".
Also: bei Seite onMouseOver einen Layer über den Link stellen, den Text im Layer mit CSS formatieren.

Popup-Seite Anzeigebeispiel: So sieht's aus

Sourcecode:

<html>

<head>

<style type="text/css">
<!--
  a:link  { color:#0FA00F; text-decoration:none; }
  a:hover { color:#000000; font-style:italic; text-decoration:none; }
  a.hover { color:#000000; font-style:italic; text-decoration:none; }
//-->
</style>

</head>

<body bgColor="#F0F0F0">

<script language="JavaScript1.2" type="text/javascript">
<!--

var ns = document.layers ? true : false;

function HoverInit()
{
  if (onLoadOld)
    onLoadOld();
  tmpLayer = new Layer(1);
  tmpLayer.bgColor = document.bgColor;
}

var obj = null;
var tmpLayer = null;
var onLoadOld = null;

if (ns) {
  if (window.onload)
    onLoadOld = window.onload;
  window.onload = HoverInit;
  document.captureEvents(Event.MOUSEOVER);
  document.onmouseover = Hover;
}

function Hover(evt)
{
  document.routeEvent(evt);

  if (tmpLayer && tmpLayer.visibility == 'hide' && evt.target.text) {

    obj = evt.target;

    tmpLayer.left = obj.x;
    tmpLayer.top  = obj.y;
    tmpLayer.width = 1;

    with (tmpLayer.document) {
      open();
      write('<nobr><a href="'+obj.href+'" class="hover"' +
            (obj.target ? ' target="' + obj.target + '"' : '') +
            '>'+obj.text+'</a></nobr>');
      close();
    }

    tmpLayer.visibility = 'show';

    document.captureEvents(Event.MOUSEMOVE);
    document.onmousemove = Hoveroff;

  }

}

function Hoveroff(evt)
{
  if (tmpLayer && evt.target != tmpLayer.document.links[0] && evt.target != obj) {

    tmpLayer.visibility = 'hide';
    document.releaseEvents(Event.MOUSEMOVE);

  }
}

//-->
</script>

<center><a href="javascript:alert('Erster Link')">| Erster Link |</a></center>
<br><br>

<a href="javascript:alert('Sei nicht so neugierig')">| Und noch einer... |</a><br><br>

</body>
</html>

Hinweis:

Das Script sollte am besten als externes Script ausgelagert werden.
Die Formatierung für den Hover-Effekt wird im Netscape Navigator mit der CSS-Angabe a.hover (nicht a:hover) bestimmt.

Beschreibung:

Beim Überfahren eines Links mit der Maus, wird dieser in dem Beispiel nicht mehr unterstrichen sondern kursiv angezeigt.

Funktion HoverInit():
Beim Laden des Dokuments wird ein Layer für den Hover-Effekt erzeugt und die Hintergrundfarbe auf die des Dokuments gesetzt.

Funktion Hover(evt):
Der erzeugte Layer wird an die Stelle des Links geschoben und der Inhalt auf den neu formatiertem Link abgeändert.

Funktion Hoveroff(evt):
Der Layer wird versteckt.

Teil von SELFHTML aktuell Teil von Artikel Teil von Dynamisches HTML

© 2007 bereichsübergreifende Seite Impressum