Stoppt die Vorratsdatenspeicherung! Jetzt klicken &handeln! Willst du auch an der Aktion teilnehmen? Hier findest du alle relevanten Infos und Materialien:

Navigation:

Besucherzähler:

  • Derzeit online: 4
  • Insgesamt: 47457

Spamfresser:

  • Spams: 11679

Seite abblenden

Kategorie JavaScript

Datum: 07.04.2008, 19:47 - Autor: Manko10

Ein Effekt, den es vor allem in Verbindung mit AJAX-Anwendungen oft zu sehen gibt: plötzlich verdunkelt sich die Seite.
Dieses Abblenden der Seite ist an sich eigentlich gar nicht so schwer zu erzeugen, da es sich nur um einen halbtransparenten Layer über der Seite handelt. Wie das geht, erkläre ich in diesem Tutorial.

Zuerst sollte man sich klar machen, welche Programmiertechnik man verwenden will. Eine einfache Funktion? Nein, wir brauchen einen Container, der mehrere Elemente beinhalten kann. Also eine Klasse? Nein auch nicht. Aber es geht schon in die Richtung. Nehmen wir ein Literal. Literale sind Variablen, die Eigenschaften und Methoden beinhalten können, also ein Objekt.
Die Syntax ist dabei ziemlich einfach:
Code:
1:
2:
3:
4:
5:
6:
var literal = {
    eigenschaft : 'Wert',
    methode : function() {
        // ...
    }
};
Einzelne Elemente werden dabei jeweils mit Kommata getrennt.

Fangen wir also an und legen zunächst zwei Eigenschaften (oder auch Attribute) fest. Die erste Eigenschaft wird das Layer-Element selbst enthalten, die zweite einen Wert für die maximale Undurchsichtigkeit (ein Wert von 0 = durchsichtig bis 1 = undurchsichtig). Letztere belegen wir mit dem Standardwert 0.7:
Code:
1:
2:
3:
4:
var pageLayer = {
     layerElement    : null,
     maxLayerOpacity : 0.7
};

Nun fehlen noch die Methoden, welche den Layer erzeugen und einblenden und wieder ausblenden und aus dem Dokument entfernen.

Zunächst die Methode, die das Erzeugen und Löschen des Layers erledigt. Da wir diese Methode für beide Aktivitäten verwenden, muss zunächst geprüft werden, ob der Layer bereits existiert. Ist dies nicht der Fall, wird der Layer neu erzeugt, andernfalls gelöscht.
Auf die dabei verwendeten DOM-Methoden gehe ich nicht ein. Wenn du genaueres dazu wissen willst, benutze bitte eine Suchmaschine deines Vertrauens.
Code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
addRemoveLayer : function() {
    if (this.layerElement == null) {
        // Layer-Element erstellen
        this.layerElement = document.createElement('div');
        
        // Layer zum Dokument hinzufügen
        document.getElementsByTagName('body')[0].appendChild(this.layerElement);
    } else {
        // Layer wieder entfernen
        document.getElementsByTagName('body')[0].removeChild(this.layerElement);
        this.layerElement = null;
    }
}
Wie du siehst, kann - wie in einer Klasse - mit dem Schlüsselwort this auf die eigenen Elemente des Literals zugegriffen werden.

So, bisher merkt man noch recht wenig von diesem Layer, da er noch in keiner Weise formatiert wurde. Holen wir das also nach, indem wir in den if-Zweig der eben geschriebene Methode folgendes einfügen:
Code:
1:
2:
3:
4:
5:
6:
7:
8:
this.layerElement.style.position        = 'absolute';
this.layerElement.style.top             = '0px';
this.layerElement.style.left            = '0px';
this.layerElement.style.width           = '100%';
this.layerElement.style.height          = document.documentElement.scrollHeight + 'px';
this.layerElement.style.minHeight       = '100%';    // für den Internet Explorer
this.layerElement.style.backgroundColor = '#000';
document.documentElement.style.overflow = 'hidden';
Hierbei wird der Layer formatiert.
Da wir dem Dokument mit document.documentElement.style.overflow = 'hidden'; die Scrolleisten geklaut haben, müssen wir sie natürlich anschließend wiederherstellen, also muss in den else-Zweig noch das hinein:
Code:
1:
document.documentElement.style.overflow = 'visible';

Machen wir mit der zweiten Methode weiter, die das Ein- und Ausblenden des Layers übernimmt.
Damit der Layer auch halbtransparent ist, bedienen wir uns der CSS-Eigenschaft opacity. Weil CSS 2 für den IE jedoch eine Fremdsprache ist, kann er mit CSS 3 erst recht nichts anfangen und drum müssen wir mit filter:Alpha(opacity=xyz) nachhelfen.
Ich schreibe zuerst den vollständigen Code und erläutere ihn dann:
Code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
fadeLayer : function(addend) {
    var opacity;
    
    if (arguments[1] == null) {
        this.addRemoveLayer();

        
        if (addend > 0) {
            opacity = 0;
        } else if (addend < 0) {
            opacity = this.maxLayerOpacity;
        } else {
            return;
        }
    } else {
        opacity = arguments[1];
    }
    
    opacity += addend;
    opacity = Math.round(opacity * 10) / 10;
    
    if (opacity > this.maxLayerOpacity) {
        return;
    } else if (opacity < 0) {
        this.addRemoveLayer();
        return;
    }
    
    if (navigator.userAgent.indexOf('MSIE') > -1) {
        this.layerElement.style.filter = 'Alpha(opacity=' + (opacity * 100) + ')';
    } else {
        this.layerElement.style.opacity = opacity;
    }
    
    setTimeout('pageLayer.fadeLayer(' + addend + ', ' + opacity + ');', 20);
}
Der Parameter addend beinhaltet die Schrittzahl, um die der Layer ein- oder ausgeblendet wird. Zum Einblenden muss diese positiv und zum Ausblenden negativ sein. Es handelt sich um einen Wert zwischen 0 und 1.
Da JavaScript es bekanntlich nicht so genau mit den Parametern nimmt, machen wir uns das doch zunutze. Die Methode muss nämlich unterscheiden können, ob sie gerade vom User aufgerufen wurde oder durch ein Timeout, das wir am Ende der Methode setzen.
Das machen wir mit einem weiteren Parameter, der in der eigentlichen Parameterliste nicht angegeben ist. Um alle Parameter auszulesen, die der Methode übergeben wurden, benutzen wir das automatisch erstellte Array arguments. Ist also arguments[1] (der zweite Parameter) nicht übergeben, so handelt es sich um den ersten Aufruf der Methode, also durch die von außen vom User. In diesem Falle muss der Layer also zuerst noch erzeugt werden.

Dann wird geprüft, ob aufwärts oder abwärts gezählt werden soll. Ist 0 übergeben, so wird die Methode kommentarlos beendet, da das keinen Sinn hätte.

Die Variable opacity enthält nun den Wert der aktuellen Transparenz. Dieser wird danach um den angegebenen Zähler verändert. Weil hierbei aber oft Rundungsfehler auftreten, wende ich einen kleinen Trick an. Ich runde die Kommazahl, die ich vorher mit 10 multipliziert habe, auf die nächste Ganzzahl auf und teile das Ergebnis wieder durch 10. Damit habe ich wieder eine korrekte Zahl.

Damit der Vorgang aber nicht endlos läuft, wird jetzt geprüft, ob die Variable über dem definierten Maximum oder unterhalb von 0 liegt. In beiden Fällen wird die Methode verlassen. Bei letzterem wird der Layer aber vorher noch aus dem Dokument entfernt.

Was jetzt noch passiert, ist nicht allzu spannend. Anhand des Benutzeragenten prüfen wir, ob der User den IE verwendet oder nicht und setzen die aktuelle Transparenzstufe mit den jeweils möglichen Mitteln.
Zu beachten gilt hierbei, dass der IE nicht eine Zahl zwischen 0 und 1 sondern zwischen 0 und 100 erwartet. Deshalb die Multiplikation mit 100.

Im darauf folgenden Schritt wird die Methode mit einem Timeout nochmals aufgerufen, diesmal mit zweitem Parameter.

Das ist es im Grund auch schon. Es fehlt aber noch etwas Entscheidendes: wenn der User auf den Layer klickt, soll dieser auch wieder ausgeblendet werden.
Dazu brauchen wir einen Event-Handler. Schreibe deshalb in die Methode pageLayer.addRemoveLayer() noch diesen Code:
Code:
1:
2:
3:
this.layerElement.onmousedown = function() {
    pageLayer.fadeLayer(-0.1, pageLayer.maxLayerOpacity);
}
Damit wird dem Layer ein Event-Handler zugewiesen.
Warum verwende ich hier nicht this? Ganz einfach. Die definierte anonyme Methode wird nicht direkt im Kontext des Literals ausgeführt, sondern per Event-Handler. Also muss ich auch den von außen sichtbaren Namen des Literals verwenden. Das ist auch der Grund, weshalb ich eingangs keine Klasse gewählt habe, da ich dann ja den späteren Namen des Objekts nicht kennte.

Hinweis für Fortgeschrittene:

Der Weg, addEventListener() für das Zuweisen eines Event-Handlers zu nehmen, wäre zwar der schönere Weg, aber dann müsste ich zu viel herumprogrammieren, um auch dem IE beizubringen, dass er dem Layer einen Event-Handler zuweisen soll. Er beharrt derzeit noch auf der Eigenkreation attachEvent(). Das einfache Zuweisen von onmousedown wird hingegen von jedem gängigen Browser unterstützt und reicht in diesem Falle auch aus.


Das ist dann auch endgültig alles. Ganz schon viel für so ein kleines Tutorial ;) .
Zum Schluss natürlich nochmal das gesamte Skript:
Code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
/*********************************************************
 * Page layer function
 * Copyright © 2008 by Janek Bevendorff
 * 
 * This Code is free to use but it would be nice if
 * you leave this comment in your projects.
 * For more Tutorials visit <http://www.openwebboard.org>
 **********************************************************/

var pageLayer = {
    layerElement    : null,
    maxLayerOpacity : 0.7,
    
    addRemoveLayer : function() {
        if (this.layerElement == null) {
            // create layer element
            this.layerElement = document.createElement('div');
            
            // attach event
            this.layerElement.onmousedown = function() {
                pageLayer.fadeLayer(-0.1, pageLayer.maxLayerOpacity);
            }
            
            // set styles of layer element
            this.layerElement.style.position        = 'absolute';
            this.layerElement.style.top             = '0px';
            this.layerElement.style.left            = '0px';
            this.layerElement.style.width           = '100%';
            this.layerElement.style.height          = document.documentElement.scrollHeight + 'px';
            this.layerElement.style.minHeight       = '100%';    // for IE
            this.layerElement.style.backgroundColor = '#000';
            document.documentElement.style.overflow = 'hidden';
            
            // add layer to body
            document.getElementsByTagName('body')[0].appendChild(this.layerElement);
        } else {
            // remove layer and make document scrollable
            document.getElementsByTagName('body')[0].removeChild(this.layerElement);
            document.documentElement.style.overflow = 'visible';
            this.layerElement = null;
        }
    },
    
    fadeLayer : function(addend) {
        var opacity;
        
        // if not called by timeout
        if (arguments[1] == null) {
            // add layer
            this.addRemoveLayer();
            
            if (addend > 0) {
                opacity = 0;
            } else if (addend < 0) {
                opacity = this.maxLayerOpacity;
            } else {
                return;
            }
        } else {
            opacity = arguments[1];
        }
        
        opacity += addend;
        
        // prevent rounding errors
        opacity = Math.round(opacity * 10) / 10;
        
        // if maximum or minimum is exceeded
        if (opacity > this.maxLayerOpacity) {
            return;
        } else if (opacity < 0) {
            // remove layer before exit
            this.addRemoveLayer();
            return;
        }
        
        // check for Internet Explorer
        if (navigator.userAgent.indexOf('MSIE') > -1) {
            this.layerElement.style.filter = 'Alpha(opacity=' + (opacity * 100) + ')';
        } else {
            this.layerElement.style.opacity = opacity;
        }
        
        setTimeout('pageLayer.fadeLayer(' + addend + ', ' + opacity + ');', 20);
    }
};
Um den Code auszuprobieren, musst du ihn nur in einer JavaScript-Datei speichern und diese in eine HTML-Datei einbinden.
Um die Seite abzublenden, reicht der schlichte Befehl
Code:
1:
pageLayer.fadeLayer(0.05);

Fertig!

Natürlich freue ich mich über jeden konstruktiven Kommentar. Was war gut? Was war nicht so gut? Bei solchen langen Artikel kann es gut sein, dass nicht alles gleich verständlich ist. Wenn du das Gefühl hast, dass etwas aus diesem Tutorial an dir vorbeigegangen ist, dann kannst du das gerne in einen Kommentar fassen.
Sei doch mutig, dich zu äußern! :)

Seiten: (1/1) 1


War dieses Tutorial hilfreich?

7 Kommentare:

hilfreiches tut

Datum: 29.04.2008, 21:35 - Autor: Gast

Hallo :)
ich finde dieses tutorial ist mit grosser mühe erstellt worden. den code kann man ja mal kopieren und wenns funtzt ist das ziel ja eigentlich schon erreicht, weil man eine funktion "meistens" nur zum laufen bringen will.
lg gandonit

Danke für das Tuorial

Datum: 02.04.2009, 21:22 - Autor: Nixe

Hallo,
danke für das Tutorial hat mir sehr weitergeholen aber eine Anmerkung habe ich noch.

In der Funktion addRemoveLayer sollte am Ende des else Zweiges noch ein this.layerElement = null. Sonst kann man nur ein mal Ausblenden. Danach gibt es eine böse Fehlermeldung. So funktioniert es bei mir:

if (this.layerElement == null) {
...
} else {
// remove layer and make document scrollable
document.getElementsByTagName('body')[0].removeChild(this.layerElement);
document.documentElement.style.overflow = 'visible';
this.layerElement = null;
}

mfg
Nixe

Datum: 02.04.2009, 21:35 - Autor: Manko10

Hi Nixe,

vielen Dank für die Ergänzung, sie wurde in das Tutorial eingefügt.
Ich denke, ich werde in nächster Zeit auch mal eine Neuauflage dieses Tutorials schreiben, in dem noch einige nützliche Sachen hinzugefügt werden, wie z.B. eine Lightbox in der Seitenmitte.

Datum: 31.07.2009, 12:09 - Autor: User

Hi Manko10,

vielen Dank für Dein sehr hilfreiches Script!
In der Tat bin ich auch sehr interessiert in einer Fortsetzung, z.B. angedeutete Lightbox, oder einfach Elemente, die nicht von der Abdunkelung erfasst werden sollen.

take care, gummibär

Lightbox

Datum: 21.08.2009, 14:25 - Autor: User

Hi Manko10,

ich bin's nochmal! Dein Script hat mir inzwischen gute dienste geleistet!
Wenn Du »this.layerElement.style.minHeight« genauso wie »this.layerElement.style.Height« mit »document.documentElement.scrollHeight+'px';« füllst, dann klappt's auch mit Firefox!
Die beiden »document.documentElement.style.overflow« kannst vergessen.

Untenstehend findest Du mein erweitertes Script für eine (Video-)Lightbox.

cu & glg

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>Videos</title>
<style>
img {border-color:transparent;margin:0px 5px}
span {width:150px;height:165px;float:left}
b {margin-left:5px}
i {font-size:smaller}
</style>
<script language=javascript>
function flv(video,w,h){
var box=document.getElementById("flvplayer" ;)
var playersite=document.config.playersite.checked?"intern":"open"
var controlbar=document.config.controlbar.checked?"bottom&autostart=true":"over"
var displayclick=document.config.displayclick.checked?"fullscreen":"play"
if(controlbar=="bottom&autostart=true" ;) {h+=20;box.style.clip="rect(0px,"+w+"px,"+(h-1)+"px,0px)"}
var jpg="inhalt"+video.substring(video.lastIndexOf("/" ;) ,video.lastIndexOf("." ;) )+".jpg"
var content=
"<object classid=clsid :D 27CDB6E-AE6D-11cf-96B8-444553540000 name=player width="+w+" height="+h+">"+
"<param name=movie value=flvplayer.swf>"+
"<param name=allowfullscreen value=true>"+
"<param name=flashvars value=file="+video+"&image="+jpg+"&controlbar="+controlbar+"&displayclick="+displayclick+">"+
"<object type=application/x-shockwave-flash data=flvplayer.swf width="+w+" height="+h+">"+
"<param name=movie value=flvplayer.swf>"+
"<param name=allowfullscreen value=true>"+
"<param name=flashvars value=file="+video+"&image="+jpg+"&controlbar="+controlbar+"&displayclick="+displayclick+">"+
"<h3>Sie haben möglicherweise JavaScript deaktiviert oder verwenden eine ältere Version des Adobe Flash Player.<br><a href=http://get.adobe.com/flashplayer>Hier erhalten Sie die neueste Version des Flash Player.</a></h3>"+
"</object>"+
"</object>"
if(playersite=="intern" ;) {
pageLayer.fadeLayer(0.05)
box.style.left=(document.body.offsetWidth-w)/2+"px"
box.style.top="200px"
box.style.display="block"
box.innerHTML=content}
else{
var fenster=window.open("","","width="+w+",height="+h+",left="+(screen.availWidth-w)/2+",top="+(screen.availHeight-h)/2)
with(fenster.document){
open()
write("<body style=margin:0>"+content)
close()}
fenster.focus()}}
var pageLayer={
layerElement:null,
maxLayerOpacity:0.8,
addRemoveLayer:function(){
if(this.layerElement==null){
this.layerElement=document.createElement("div" ;)
this.layerElement.onmousedown=function(){
pageLayer.fadeLayer(-0.1,pageLayer.maxLayerOpacity)
var box=document.getElementById("flvplayer" ;)
box.style.display="none"
box.innerHTML=""}
this.layerElement.style.position="absolute"
this.layerElement.style.top="0px"
this.layerElement.style.left="0px"
this.layerElement.style.width="100%"
this.layerElement.style.height=document.documentElement.scrollHeight+"px"
this.layerElement.style.minHeight=document.documentElement.scrollHeight+"px"
this.layerElement.style.backgroundColor="black"
document.getElementsByTagName("body" ;) [0].appendChild(this.layerElement)}
else{
document.getElementsByTagName("body" ;) [0].removeChild(this.layerElement)
this.layerElement=null}},
fadeLayer:function(addend){
var opacity
if(arguments[1]==null){
this.addRemoveLayer()
if(addend>0)opacity=0
else if(addend<0)opacity=this.maxLayerOpacity
else return}
else opacity=arguments[1]
opacity+=addend
opacity=Math.round(opacity*10)/10
if(opacity>this.maxLayerOpacity)return
else if(opacity<0){
this.addRemoveLayer()
return}
if(IE='\v'=='v')this.layerElement.style.filter="Alpha(opacity="+(opacity*100)+" ;) "
else this.layerElement.style.opacity=opacity
setTimeout("pageLayer.fadeLayer("+addend+","+opacity+" ;) ",20)}}
</script>
</head>
<body style=font-family:Arial;font-size:smaller;text-align:center>
<div id=flvplayer style=position:fixed></div>
<form style=position:absolute;text-align:right name=config action="">Flashplayer in diesem Fenster <input type="checkbox" name="playersite" value="intern" checked><br>Navigationsleiste / Autostart <input type="checkbox" name="controlbar" value="bottom" checked><br>Fullscreen bei Mausklick <input type="checkbox" name="displayclick" value="fullscreen" checked></form>
<p><font size=7 face=Verdana color=steelblue><b><em>Videos</em></b></font></p><table><tr><td>
<span><a href="Beispielvideo.flv" onclick="flv(this.href,320,240);return false" title="Beispielvideo"><img src="inhalt/Beispielvideo.jpg"></a><b>Beispielvideo</b> [flv]<i>&nbsp;1:23</i></span>
</body>
</html>

Datum: 23.08.2009, 12:21 - Autor: Manko10

Hi,
vielen Dank für deine Ergänzungen, ich werde sie mit der Zeit einarbeiten und beizeiten wird es auch eine Fortsetzung geben.
Die letzten vier Wochen war ich aber im Urlaub und muss mich erstmal wieder zu Hause einfinden, meine Finger wieder eintippen und mich durch das durchwühlen, was in der Zeit alles so passiert ist. ;-)

Grüße und Danke
Manko10

Datum: 27.08.2009, 18:51 - Autor: Thomas

Wie kann man den Effekt in einen beliebigen DIV-Container oder den Z-Index verschieben? Ich habe auf meiner Seite einige Javascript-Elemente, die nicht im Body verankert sind und deshalb immer auf dem Layer liegen, obwohl sie dahinter sein sollten.

Alle Bemühungen, die Zeile mit "getElementsByTagName('body')" umzubauen sind kläglich gescheitert. Gibt es etwas, dass ich hier übersehen habe?

Kommentar schreiben: