nakedandfamous: [js]: x/y position eines links ermitteln

Ich hab eine liste an links (ein link pro zeile).
Nun möchte ich, dass bei markierung mit der tab-taste jeweils in relativer position zum markierten link (zum beispiel jeweils direkt davor) ein layer mit einer grafik erscheint, der auf einen weiteren tab-druck dann wieder weiter vor den nächsten link wandert.
Die Frage ist also, wie krieg ich die position eines links (der dann etwa eine eigene id hat) raus (und geht das mit javascript überhaupt?) um dann relativ zu ihm den grafiklayer erscheinen zu lassen?

Grüße,
Bernd.

  1. Hallo, nakedandfamous,

    Ich hab eine liste an links (ein link pro zeile).
    Nun möchte ich, dass bei markierung mit der tab-taste jeweils in relativer position zum markierten link (zum beispiel jeweils direkt davor) ein layer mit einer grafik erscheint, der auf einen weiteren tab-druck dann wieder weiter vor den nächsten link wandert.

    Kann deine Seite nur mit Tastatur und aktivierter JavaScript-Unterstützung bedient werden?

    Die Frage ist also, wie krieg ich die position eines links (der dann etwa eine eigene id hat) raus (und geht das mit javascript überhaupt?)

    Im Posting [pref:t=49578&m=271055] habe ich beschrieben, wie sich die Objekteigenschaften offsetTop und offsetLeft abfragen lassen. Zu denen könntest du anhand der offsetWidth des Links wiederum einen Wert addieren und entsprechend das Element über die Objekteigenschaft .style.top und die anderen CSS-Positionseigenschaften versetzt erscheinen lassen (visibility auf »visible« setzen).

    um dann relativ zu ihm den grafiklayer erscheinen zu lassen?

    Ja, aber im Grunde nicht wirklich. Du weißt in der Regel nicht, an welcher der Stelle im Browserfenster der Link letztendlich erscheint und ob eventuell kein Platz ist. Das lässt sich auch schwer zuverlässig prüfen, zumal du damit rechnen musst, dass zahlreiche Browser und damit Benutzer über das System stolpern werden.

    Ein rudimentäres (!) Beispiel, wie es funktionieren könnte, ohne Browserabfragen, welche hier besonders nötig wären:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Test</title>
    <style type="text/css" media="screen,tv,projection" title="Autorenformatvorlage">
    html {padding:0;}
    body {margin:0; padding:10px;}
    #bla {border:1px solid red; margin:0; padding:5px; position:absolute; top:0; left:0; visibility:hidden; /* Breite (ist unten unflexibel festgelegt auf 100px): */ width:100px; background-color:white;}
    .a {text-align:left;}
    .b {text-align:right;}
    </style>
    <script type="text/javascript">
    function zeigelayer (obj) {
     var bodywidth=document.body.offsetWidth;
     var leftundwidth=obj.offsetLeft+obj.offsetWidth;
     var platzrechts=bodywidth-leftundwidth;
     /* Ist rechts genug Platz? */
     if (platzrechts>=155) {
       /* Positioniere rechts vom Element */
       var neueposition=(leftundwidth+50)+'px';
       document.getElementById('bla').style.left=neueposition;
     } else {
      /* Ist links genug Platz? */
      if (obj.offsetLeft>=105) {
       /* Positioniere links vom Element */
       document.getElementById('bla').style.left=(obj.offsetLeft-155)+'px';
      }
     }
     document.getElementById('bla').style.top=obj.offsetTop+'px';
     document.getElementById('bla').style.visibility='visible';
    }
    function versteckelayer () {
     document.getElementById('bla').style.visibility='hidden';
    }
    </script>
    </head>
    <body>

    <p class="a">This page is <a href="bla" onfocus="zeigelayer(this);" onblur="versteckelayer();">intentionally</a> left blank.</p>
    <p class="b">This page is <a href="bla" onfocus="zeigelayer(this);" onblur="versteckelayer();">intentionally</a> left blank.</p>
    <p class="a">This page is <a href="bla" onfocus="zeigelayer(this);" onblur="versteckelayer();">intentionally</a> left blank.</p>
    <p class="a">This page is <a href="bla" onfocus="zeigelayer(this);" onblur="versteckelayer();">intentionally</a> left blank.</p>
    <p class="b">This page is <a href="bla" onfocus="zeigelayer(this);" onblur="versteckelayer();">intentionally</a> left blank.</p>

    <div id="bla">murks</div>

    </body>
    </html>

    (Diesen Code kannst du wie gesagt nicht in dieser Form verwenden, es ist keine fertig anwendbare Lösung, nur eine Konzeptbeschreibung!)
    Getestet habe ich es mit dem jeweils neusten Mozilla-Firebird, MSIE und Opera. Im Mozilla und MSIE können die Links mit Tabulator durchgeschaltet werden, im Opera mit den Tasten A und Q, und auf der jeweils gegenüberliegenden Seite sollte die murks-Box erscheinen.

    Grüße,
    Mathias

    --
    »In anderen Newsgroups werden Pseudonyme akzeptiert, es handelt sich dabei meist um Gruppen, in denen sensible Themen (z.B. psychische oder peinliche Erkrankungen o.ä.) behandelt werden.«
    1. Vielen vielen dank Mathias für deine detailierte Antwort *respekt*

      damit wars nicht mehr schwierig mein Problem zu lösen...

      Bernd

  2. Hallo noch einmal,

    Ich hab eine liste an links (ein link pro zeile).
    Nun möchte ich, dass bei markierung mit der tab-taste jeweils in relativer position zum markierten link (zum beispiel jeweils direkt davor) ein layer mit einer grafik erscheint, der auf einen weiteren tab-druck dann wieder weiter vor den nächsten link wandert.

    Vielleicht kannst du dein Ursprungsproblem konkreter und präziser beschreiben, denn je länger ich darüber nachdenke, kommen mir verschiedene Lösungen für verschiedene Probleme in den Kopf, welche sich aus deinem Posting herauslesen ließen. Insofern weiß ich nicht, ob die gepostete JavaScript-Lösung für dein spezielles Problem überhaupt angemessen ist.

    Eine andere Lesart:

    Falls du direkt vor einem Link eine Grafik erscheinen lassen willst, wenn der Link ausgewählt wird, gibt es zahlreiche viel simplere Möglichkeiten als die, die ich vorgestellt habe - die geht nämlich nur von einem irgendwie relativ positionierten Link aus, auch anders herum, als du im Beispiel genannt hast; wahrscheinlich hilft sie die folglich nicht viel weiter.

    Eine einfache Möglichkeit ist, eine solche Grafik erscheinen zu lassen, ist eine »Blindgrafik« (ein transparentes 1x1 Pixel großes Gif-Bild oder Png-Bild) vor jeden Link in der jeweiligen Größe zu stellen und die Adresse (src-Attribut) dieses Bilders zu ändern, wenn der Link ausgewählt wird. Das Bild selbst kann natürlich mit CSS über die Seite verschoben werden oder schlichtweg danebengestellt werden. Damit sparst du dir den Ärger mit der nachträglichen Positierung, da die Grafik bereits von Anfang an ihren Platz hat. Siehe dazu das images-Element http://selfhtml.teamone.de/javascript/objekte/images.htm.
    Von dieser Variante gibt es verschiedene Spielarten, du kannst beispielsweise ein CSS-Hintergrundbild auftauchen lassen, sodass das Markup selbst keine img-Elemente nötig sind. Im Mozilla geht das über a:focus ausschließlich mit CSS, in MSIE und Opera ist etwas JavaScript notwendig:

    #eins a {padding-left:20px;}
    #eins a:focus, .ausgewaehlt {background-image:url(http://forum.de.selfhtml.org/src/x2.gif); background-position:left; background-repeat:no-repeat;}

    <ul id="eins">
    <li><a href="link">link</a></li><!-- Nur Mozilla -->
    <li><a href="link" onfocus="this.className='ausgewaehlt'" onblur="this.className=''">link</a></li><!-- Opera, Mozilla und MSIE -->
    </ul>

    Das Bild ist dann Teil des Links, sozusagen.

    Weiterhin gibt es die Möglichkeit, die Grafiken zwar als img-Elemente im HTML-Code unterzubringen, sie aber über visibility:hidden zu verstecken und über einen passenden Selektor bei :focus auftauchen zu lassen... Mit JavaScript wird wieder die Klasse über className geändert.

    #zwei a {text-decoration:none;}
    #zwei a img {visibility:hidden; border-style:none;}
    #zwei a:focus img, .sichtbar {visibility:visible !important;}

    <ul id="zwei">
    <li><a href="link"><img src="http://forum.de.selfhtml.org/src/x2.gif"/> link</a></li><!-- Nur Mozilla -->
    <li><a href="link" onfocus="this.childNodes[0].className='sichtbar'" onblur="this.childNodes[0].className=''"><img src="http://forum.de.selfhtml.org/src/x2.gif"/> link</a></li><!-- Opera, Mozilla und MSIE -->
    </ul>

    childNodes http://selfhtml.teamone.de/javascript/objekte/node.htm#child_nodes ist DOM-Syntax (childNodes[0] spricht den erste Kindknoten an, das ist das img-Element), nicht sehr kompatibel, es ist wieder nur ein einfaches Theoriebeispiel.
    Auch hier ist die Grafik Teil des Links, sie könnte aber auch absolut positioniert werden, also aus dem Fluss genommen werden beispielsweise über position:absolute; left:30px;. (Bei beispielsweise position:relative; left:-20px; wird die Grafik zwar 20px um ihre Ursprungsposition verschoben, an der Ursprungsstelle bleibt jedoch ein imaginärer Platzhalter, das heißt, die nachfolgenden Elemente werden so angezeigt, als wäre die Grafik noch an ihrem alten Platz.) Dadurch könnte die zum Link gehörende Grafik auch optisch weit entfernt stehen.

    Falls du übrigens mit »Wandern« eine geschmeidige Bewegung meintest, habe ich dich falsch verstanden, ich ging von »Springen« aus (Grafik erscheint bei dem einen Link ruckartig, verschwindet kurz für eine nicht merkbare Zeit und taucht sofort wieder vor dem nächsten auf).

    Die Nennung von Opera bezieht sich immer auf die 7er-Version, die des MSIEs auf die 6er.

    Grüße,
    Mathias

    --
    »In anderen Newsgroups werden Pseudonyme akzeptiert, es handelt sich dabei meist um Gruppen, in denen sensible Themen (z.B. psychische oder peinliche Erkrankungen o.ä.) behandelt werden.«