Tooltips sind eine feine Sache. Sie lassen sich einsetzen, um zusätzliche Informationen zu präsentieren oder um Kontexthilfen anzuzeigen.
Es gibt verschiedene Methoden mittels JavaScript solche Tooltips anzuzeigen. Viele davon nutzen dazu die Title-Attribute im HTML-Tag. Das Title-Attribut ist ja schon von sich aus dazu gedacht, Tooltips anzuzeigen, unterliegt aber verschiedenen Beschränkungen:

  • Die Standardtooltips lassen sich nicht mittels CSS in Form bringen
  • Die Tooltips werden nicht angezeigt, wenn jemand das Tag mit dem Mauszeiger nicht erreichen kann, oder überhaupt keine Maus benutzt
  • Die Tooltips werden nicht wirklich lange angezeigt (Die Ausnahme bildet hier der Opera)
  • Längere Texte in Tooltips werden häufig ungünstig umgebrochen oder abgeschnitten

Die genannten Beschränkungen lassen sich umgehen, in dem man den Tooltip mittels JavaScript selbst erzeugt. Hier wird exemplarisch eine Version gezeigt, die mit jquery arbeitet.

HTML (Ausschnitt)

 <a class="useredit" title="Dieser Link öffnet die Bearbeitunsgmaske für Benutzer.
 Dort können die persönlichen Einstellungen des jeweiligen Benutzers geändert werden." href="/edituser/23">
 Benutzer 23 editieren</a>

JavaScript(Ausschnitt)

$(document).ready(function(){

$(".useredit").hover(function(){

    var content = $(this).attr("title");

    $(this).attr("title",""); // Damit der Browser keinen eigenen Tooltip zeigt,
                                      //  das Title-Attribut leeren
   // Um das Title-Attribut später wieder setzen zu können,
  // ihn in ein temporäres Attribut schreiben.
    $(this).attr("tempTitle",content); 

   var hilfeBox = $('
<div>').attr('class','tooltip');

   var ePosition = getPosition(this); // Bestimme x und y Wert des Hilfe-Links

   var eWidth = getElementWidth(this); // Bestimmte die Breite des Hilfe-Links

   $(hilfeBox).css({
        position: "absolute",
        top: ePosition[1],
        left: ePosition[0]+ eWidth +"px",
        width: 250 + "px",
        border: "2px solid red",
        padding: "6px",
        background: "#FFF"
        });

   $("div.tooltip").text(content);
   $("body").append(hilfeBox);

},function(){

 var content = $(this).attr("tempTitle"); // Den Text wieder einlesen
 $(this).attr("title",content); // Wieder in das Title-Attribut schreiben
 $(this).attr("tempTitle",""); // Temporäres Attribut leeren 

 $('div.tooltip').remove() // Tooltip entfernen
});

});

Will man die Tooltips als Hilfen zur Bedienung benutzen und gleichzeitig eine zentrale Hilfeseite bereitstellen, ergeben sich verschiedene Probleme. Insbesondere die doppelte Datenhaltung (Hilfetexte in den Title-Attributen und im HTML der Hilfeseite) verkompliziert die Wartung der Seiten unnötig. Längere Texte in den Title-Attributen sind unschön, insbesondere wenn die Texte mehrfach verwendet werden.

Um diese Hürden zu überwinden, bietet sich der Einsatz von Ajax an. Man legt eine zentrale Hilfeseite an, die sich über die Navigation erreichen läßt. Hier können Bilder, Screencasts und Texte angezeigt werden, die dem Benutzer helfen sollen. Nun können Texte aus dieser Seite mittels Ajax abgefragt und als Tooltip angezeigt werden. Außerdem lassen sich so auch andere Elemente wie Bilder anzeigen, was bei der Title-Attribut-Methode nur schwerlich möglich ist.

Seit der Version 1.2 bietet jquery in seiner load() Methode eine einfache Möglichkeit über CSS-Selektoren HTML aus einem Dokument zu extrahieren und in das DOM einzufügen. Im folgenden Beispiel wird genau diese Methode verwendet.

Zunächst wird neben ein Eingabefeld zur Suche, ein Link gesetzt, der auf den entsprechenden Anker der Hilfeseite verweist.

HTML (Ausschnitt)

 <fieldset>
  <legend>Suche</legend>
<form method="post">

<label>Suchbegriff:</label>
<input class="txt" name="textfield" type="text" />
  <a id="sH" class="hilfe" name="suche" href="hilfeseite.html#suche">?</a>
  <!-- verweist auf den entsprechenden Anker der Hilfeseite -->

<input name="Submit" type="submit" value="Suchen" />
</form>

</fieldset>

Im JavaScript wird ein Eventlistener aktiviert, der auf MouseOver den Hilfetext in einer Box anzeigt und bei MouseOut, die Box wieder aus dem DOM löscht.

JavaScript (Ausschnitt)

 $("a.hilfe").hover(function(){zeigeHilfe(this)},function(){$('#hilfeBox').remove()})

Dieser Eventlistener wird auf alle Links mit der Klasse “hilfe” gelegt, so dass man beliebig viele Hilfelinks setzen kann.

JavaScript(Ausschnitt)

// Kofigurationsparameter, kann am Anfang des JS gesetzt werden
var helpBox =
  {
      width: 250,
       id: "hilfebox"
  }
;
// Diese Funktion erzeugt die Hilfebox

function zeigeHilfe(element){

    var finalLeft = 0; // X-Position der Hilfebox wird auf Null gesetzt

/* Nun wird das href-Attribut des Links zerlegt. Die beiden Teile werden später im Ajax-Aufruf
    verwendet, um die richtige Seite abzufragen und den richtigen CSS-Selector zu verwenden.
     (s.u. HTML der Hilfeseite)
*/

    var hilfeDaten = element.href.split("#");

    var ePosition = getPosition(element); // Bestimme x und y Wert des Hilfe-Links

    var eWidth = getElementWidth(element); // Bestimmte die Breite des Hilfe-Links

    var viewSize= getViewSize(); // Darstellungsbreite ermitteln

    // wenn das Fenster über den rechten Bildrand ragen sollte, nach links verschieben
    if (ePosition[0] + eWidth + 10 + 250 > viewSize[0])
    {
        finalLeft = ePosition[0] - eWidth - 10 - helpBox.width;
    }
    // Sonst nach Links ausrichten
    else{
        finalLeft = ePosition[0] + eWidth + 10 ;
    }
      // Ein DIV bauen und ihm die ID aus den Konfigurationsparametern (s.o.) geben
    var hilfeBox = $('
<div>').attr('id', helpBox.id) 

    // Styles setzen, Rahmen und Farben sollten besser über eine
    // CSS-Datei gesetzt werden Der Einfachheit halber jetzt aber hier.

    $(hilfeBox).css({
        position: "absolute",
        top: ePosition[1],
        left: finalLeft+"px",
        width: helpBox.width + "px",
        border: "2px solid red",
        padding: "6px",
        background: "#FFF"
    });

    // Hilfebox ins DOM einhängen

    $("body").append(hilfeBox);

/* Inhalte aus der Hilfeseite laden
 hilfeDaten[0] ist hier die Hilfeseite aus dem Href-Attribut des Links,
 hilfeDaten[1] ist hier der Name des Ankers. Dieser entspricht gleichzeitig
 der ID des li-Elements der Hilfethemen. (s.u. HTML)

*/
	$("#"+helpbox.id).load(hilfeDaten[0]+"  #"+hilfeDaten[1]+" p.desc");

}

Die Hilfeseite wird per Ajax geladen. Über den CSS-Selektor wird der Inhalt des Absatzes (.desc) im entsprechenden List-Element (#suche) ausgelesen und in die Hilfebox geschrieben.
Der Link verweist dabei auf die richtige Stelle der Hilfeseite, die dann per Klick erreicht werden kann.

HTML der Hilfeseite (Auschnitt):

<ul id="hilfethemen">
	<li id="useredit"> <!--ID des Abschnitts. Muss dem Name-Attribut
   des Ankers entsprechen. -->
  <a name="useredit"></a> <!--Anker zum Verlinken des Hilfethemas -->
<h3>User Editing</h3>
<img src="http://beispiel.de/einScreenshot.jpg" alt="screenshot" />

Lorem ipsum ...</li>
	<li id="suche">
   <a name="suche"></a>
<h3>Suchfunktion</h3>
<img src="http://beispiel.de/einaAndererScreenshot.jpg" alt="screenshot" />

Per Ajax aus der Hilfeseite geladen. Lorem ipsum dolor sit amet, consetetur
     sanct...</li>
</ul>

Natürlich kann man auf diesem Wege auch ganz einfach mehrere Hilfeseiten anlegen, die nach Themen sortiert sind. Eine größere Webanwendung wird dies zweifelsfrei notwendig machen.

Eine Live-Demo des Codes
Die vollständigen Dateien zum Download

Quellen:

http://jquery.com

Tags: , , ,




Unterschiedliche Layouts nach Darstellungsbreite

Eine große Menge von Informationen übersichtlich auf einer Website zu präsentieren ist ein schwieriges Unterfangen. Zusätzlich erschwert wird es durch unterschiedliche Bildschirmauflösungen. Eine Fenstergröße von 800 x 600 als Relikt der Vergangenheit abzutun, kann sich schnell als Fehler erweisen. Denn auch wenn nur noch eine verschwindend geringe Menge Benutzer mit niedriger Auflösung das Netz bereist, ist Auflösung nicht gleich Darstellungsbreite.

Eine hohe Auflösung führt nicht zwangsläufig dazu, dass alle Fenster (und damit auch der Browser) in voller Breite genutzt werden. Viele Benutzer legen die Fenster ihrer Anwendungen bei einer hohen Auflösung nebeneinander auf den Bildschirm. Das bedeutet aber gleichzeitig, dass die Breite der Fenster wieder geringer wird. Es können diverse Toolbars im Browser aktiviert und Sidebars geöffnet sein. Die Vorgaben zur Barrierefreiheit, die der Seite zu Grunde liegen, können erfordern, die Seiteninformationen auch bei einer Auflösung von 800×600 ohne horizontales Scrolling zugänglich zu machen. Was aber dann meist in einer langen vertikalen Scrolleiste resultiert.

Es gibt verschiedene Lösungsansätze, die sich mit dieser Problematik befassen. Beispielhaft seien hier drei genannt, es existieren aber durchaus noch mehr Ansätze.

1) Ein Inhaltsbereich mit einer festgelegten Breite, der zentriert im Browser angezeigt wird. Wie zum Beispiel zu sehen auf:

http://www.microsoft.com/
http://www.apple.com/

Diese Lösung ist leicht zu implementieren, hat aber den Nachteil, dass sie dem Benutzer keinen wirklichen Mehrwehrt bei größerem Browserfenster bietet.

2) Ein sogenanntes “flüssiges Layout” (liquid Layout). Hierzu beispielhaft folgende Artikel auf “A List Apart”.

http://www.alistapart.com/articles/elastic/
http://www.alistapart.com/articles/negativemargins/

Dieser Lösungsansatz ist ebenfalls leicht zu implementieren, hat aber Nachteil, dass Texte schnell unleserlich werden, je nach dem wie weit oder wie schmal das Browserfenster geöffnet wurde. Bei Bildern im Contentbereich können größere Probleme auftreten, weil diese sich nicht so einfach skalieren lassen. Außerdem kann es sogar sein, dass bestimmte Bereiche von anderen überlagert werden.

3) Eine rechte Spalte, die weniger wichtige Inhalte enthält.

http://www.sueddeutsche.de/
http://www.adobe.com/

Ebenfalls leicht zu implementieren. Es muss aber in Kauf genommen werden, dass die rechte Spalte aus dem Sichtfeld verschwinden kann. Die Designmöglichkeiten sind ein wenig eingeschränkt und die horizontale Scrollleiste führt möglicherweise zur Verwirrung bei den Benutzern.

Ein weiterer Lösungsansatz(1), der aber keinen Anspruch erhebt, der heilige Gral zu sein, ist eine Methode, das Layout abhängig von der Breite des Darstellungsbereichs zu verändern. Es bietet sich hierbei die Möglichkeit, unterschiedliche Layouts für unterschiedliche Breiten zu erstellen und diese dann mittels Javascript zu aktivieren. Wie das geht, wird in den folgenden Abschnitten geschildert. Dabei ist zu beachten: Layout meint hier nicht HTML + CSS, sondern nur CSS! Das Markup bleibt unverändert.

Alle Dateien zu diesem Artikel als können als zip heruntergeladen werden.

Das Fundament bildet dieses HTML (Auszug!)

...
<div id="linkeSpalte">
<fieldset>
<legend>Suche</legend>
<form method="post">
<input class="txt" name="textfield" type="text" />
<input name="Submit" type="submit" value="Suchen" /></form>

</fieldset>
<ul>
	<li><a href="#">Über uns</a></li>
	<li><a href="#">Katalog</a></li>
	<li><a href="#">Kontakt</a></li>
	<li><a href="#">Impressum</a></li>
</ul>
</div>
<div id="content">
<div class="textContent">
<h2>Artikel 1</h2>
Lorem ipsum...</div>
<div class="textContent">
<h2>Artikel 2</h2>
Lorem ...
<div class="textContent">
<h2>Artikel 3</h2>
Lorem ...</div>
<div class="textContent">
<h2>Artikel 4</h2>
....</div>
</div>
<div id="rechteSpalte">
<h3>Inhalte auf der rechten Seite</h3>
Lorem ipsum dolor sit amet

...</div>
</div>

Wichtig ist dabei, dass im <head> direkt alle Stylesheets eingebunden werden und das Standard-Layout an letzter Stelle dieser Aufrufe liegt! So werden die Angaben aus den anderen Dateien überschrieben. Siehe oben.
Um den Pflegeaufwand zu reduzieren, sollte man eine (oder mehrere) Basis-CSS-Datei einbinden und nur noch die Unterschiede der verschiedenen Layouts in entsprechenden Dateien hinterlegen. Der <link> zu dieser Datei darf kein Title-Attribut aufweisen! (s.u.)

Bei 800px Fensterbreite wird das HTML mit CSS in diese Form gebracht:

Navigation, Inhaltsbereich und Zusatzinformationen untereinander.

Eine LIVE-Demo findet sich hier.

Für eine Breite ab 1024px sieht es dann so aus:

Darstellung bei 1024px

Navigation, Inhaltsbereich und Zusatzinformationen nebeneinander. Die Elemente des Inhaltsbereichs untereinander.

Eine LIVE-Demo findet sich hier.

Und bei 1200 oder mehr Pixeln Breite kommt dieses Layout zum Einsatz:

Darstellung bei 1200px

Navigation, Inhaltsbereich und Zusatzinformationen nebeneinander. Die Elemente des Inhaltsbereichs neben- beziehungsweise untereinander.

Eine LIVE-Demo findet sich hier.

Um das richtige Stylesheet zu ermitteln und zu aktivieren, wird JavaScript benötigt.

Zunächst muss ein EventListener eingesetzt werden, um auf die Änderungen an der Größe des Darstellungsbereichs zu reagieren:

In diesem Beispiel wird der EventListener von jquery benutzt.
[sourcecode language="javascript" ]
$(window).resize( function() { setStylesheet() } );[/sourcecode]
Mittels des EventListeners wird eine Funktion aufgerufen, die das richtige Stylesheet auswählt und aktiviert.

/* Zur Konfiguration werden die Stylesheets in ein Mapping geschrieben*/  

var stylesheets = [  { width : 1023, css : '800' },

{ width : 1200, css : '1024' },

{ width : 5000, css : 'default' },

];

function setStylesheet(){

var vWidth = getViewSize()[0]; /*Darstellungsbreite betsimmen */

for (var i = 0, len = stylesheets.length; i < len; i++) { /*Konfigurationsdaten durchlaufen */

if (stylesheets[i].width > vWidth) {

var css = stylesheets[i].css; /* Passendes Stylesheet aussuchen */

break; /* Wenn gefunden Schleife beenden */

}

}

if( css){activateStylesheet( css ); } /* Stylesheet aktivieren */

}
[sourcecode]
Um die sichtbare Breite des Fensters zu ermitteln, wird folgendes JavaScript eingesetzt.
[sourcecode language="javascript"]
function getViewSize(){ 

var size = [0, 0]; /*Reset*/ 

var de = document.documentElement;

var width = self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;

/*Für FireFox, Opera, Netscape, Konqueror, Safari und alle Browser die window.innerWidth verstehen

* oder für IE6 im standardkonformen Modus

* oder für alle Fälle

*/

var height = self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;

/*siehe oben */

size = [

width,height

];

return size;

}

Diese Funktion aktiviert den entsprechenden <link> im <head> des HTML. Dabei werden zunächst alle Stylesheet-Link-Tags deaktiviert, die über ein Title-Attribut verfügen. Im Anschluss wird das ausgewählte Stylesheet aktiviert. Stylesheet-Link-Tags, die kein Title-Attribut haben, bleiben hiervon unberührt. In diesen können grundlegende Anweisungen für alle Layouts gesetzt werden, wie zum Beispiel über Farben und Typographie.

function activateStylesheet(styleTitle)
{
var currTag="";
if (document.getElementsByTagName){ 

var links = document.getElementsByTagName("link");/*Finde alle Link-Tags */ 

/* Über alle Links-Tags iterieren, siehe auch Hinweisbox am Seitenanfang */
  for (var i = 0; (currTag = links[i]); i++)  {

/* Finde die Link-Tags, die sich auf ein Stylesheet beziehen und die ein Title-Attribut                                                                                                                                 haben*/
    if (currTag.getAttribute("rel").indexOf("style") != -1 && currTag.getAttribute("title")) {

currTag.disabled = true; /* Deaktiviere den Link-Tag */

if(currTag.getAttribute("title") == styleTitle){  /* Finde das zu aktivierende Stylesheet */

currTag.disabled = false; /* Aktivieren */
       }
    }
}
}

return true;
}

Alle Dateien zu diesem Artikel als können als zip heruntergeladen werden.

Zum Anfang des Artkels

Quellen:
1 http://www.themaninblue.com/
http://www.alistapart.com/

Tags: , , ,