# jQuery: Aufklappen des Contents nach Klick auf Menülink



## yuro (11. September 2013)

Hallo,

ich habe eine Frage zu einer jQuery Funktion.

Und zwar möchte ich, dass wenn ich auf einen Menüpunkt in der Navigation klicke, sich dann erst der Content öffnet im Sinne von slideDown() und wenn man auf denselben Menüpunkt wieder klickt soll der Content wieder nach oben zugehen im Sinne von slideUp().

Ich könnte es evtl mit slideToggle() machen, nur ist das Problem, dass wenn ich auf einen anderen Menüpunkt klicke, es nicht so funktioniert wie ich es möchte. Denn wenn man auf einen anderen Menüpunkt klickt soll der Content zugeklappt und der Content vom neuen Menüpunkt aufgeklappt werden.

Kann mir da einer einen Tipp geben, wie ich das realisieren könnte?

Ich danke jedem für seine Hilfe


----------



## Jan-Frederik Stieler (11. September 2013)

Hallo,
in meiner Snippetsammlung hab ich ein jQuery accordion: http://jsbin.com/OHocIl/2/edit
Das sollte eigentlich sowas sein was du suchst.

Viele Grüße


----------



## yuro (12. September 2013)

Hej Jan,

Ich hab mir deinen Code mal angeschaut. Sieht sehr interessant aus. Nur weiss ich jetzt nicht genau wie ich das auf meine Listenelemente übertragen soll. Der Content soll ja per AJAX übertragen werden.


So sieht mein HTML Code aus:

```
<nav id="header-nav">
        	<ul id="menu">
            	<li><a id="home" href="#">Home</a></li>
                <li><a id="bio" href="#">Biografie</a></li>
                <li><a id="referenzen" href="#">Referenzen</a></li>
                <li><a id="links" href="#">Links</a></li>
                <li><a id="kontakt" href="#">Kontakt</a></li>
            </ul>
        </nav>

<section>
        <div class="result">
        	//hier lädt die load()-Funktion den Content Inhalt ohne das die ganze Page neu lädt.
        </div>
    </section>
```

jQuery:

```
$("#home").click(function() {
        $(".result").load("index.html");
    });
	
    $("#bio").click(function() {
       	$(".result").load("bio.html");
    });

....
```

Ist der bisherige jQuery code bei dem Accordion dann überflüssig?


----------



## tombe (12. September 2013)

So wie du es hast, reicht das hier aus:


```
$(".link").click(function() {
	var id = $(this).attr("id");
	$(".result").fadeOut("slow", function() {
		$(".result").load(id + ".html");
		$(".result").fadeIn("slow");
	})
});
```

Die ID des jeweiligen Links entspricht den Dateinamen, bzw. den Dateinamen ohne Endung.

Die einzelnen Click-Funktionen brauchst du dann natürlich nicht mehr!


----------



## Jan-Frederik Stieler (12. September 2013)

Hi,
hier ist dann noch eine Variante mit Slide. Ist aber beim ersten Slide nicht so ganz schön wie das Faden.

Ich würde den zu ladenden Content mir aus dem href besorgen, dann funktionieren deine links auch wenn JS deaktiviert ist.

http://jsbin.com/OHocIl/4/edit

Viele Grüße


----------



## tombe (12. September 2013)

Das mit dem href ist ein gutes Argument.


```
$("a.link").bind("click", function(e){
	e.preventDefault();
	href = $(this).attr("href");
	$(".result").fadeOut("slow", function (){
		$(".result").load(href);
		$(".result").fadeIn("slow");
	});
});
```

Alle Links die es betrifft, bekommen die Klasse "link" zugewiesen.


----------



## jeipack (12. September 2013)

@tombe:
Da fehlt noch ein event..preventDefault()


----------



## Jan-Frederik Stieler (12. September 2013)

@tombe: kennst du eine Möglichkeit das mit dem Slide beim ersten click zu verbessern? 
Also das dort auch schon das so schön aufgeht und nicht einfach nur erscheint.

Grüße


----------



## yuro (13. September 2013)

Erst einmal einen riiiiiiiesen Dank an tombe und jan . Das ist genau das was ich gesucht habe. Es funktioniert einwandfrei.

Hab da noch eine Frage zu einer Funktion. Und zwar klappt sich jetzt alles prima auf und zu. doch es soll auch die Möglichkeit geben, dass wenn erst einmal ein Menü aufgeklappt wurde, man es durch ein X schließen kann. Momentan ist nur der Anfang (sozusagen wenn man auf die Seite gelangt) die .result-box nicht zu sehen da ich sie mit einem {display:none;} versehen habe.

Ich weiss, dass ich mit der jQuery Funktion removeClass(); dies vollenden kann. Nur wie füge ich sie dem obigen Code hinzu?


----------



## tombe (13. September 2013)

@Jan: Ich denke es liegt an zwei Dingen das der Text beim ersten Mal so "plötzlich" erscheint.

1) Der Container "result" ist leer, füge einfach mal ein nbsp; und es wird schon besser.

2) Die Angabe "slow" ist nicht langsam genug. Wenn man anstatt "slow" z.B. den Wert 1000 macht, erscheint der Text auch beim ersten Mal nicht so plötzlich.

Wenn man nur ein Whitespache einfügt aber den Zeitwert nicht ändert oder auch umgekehrt, ändert sich nichts. Nur wenn beide Angaben geändert werden hilft es was.


----------



## tombe (13. September 2013)

```
$(document).ready(function(){

$("a.link").bind("click", function(e){
	e.preventDefault();
    href = $(this).attr("href");
    $(".result").fadeOut("slow", function (){
        $(".result").load(href, function () {
			$(".result").prepend("<span class='x'><b>X</b></span>");
		});
        $(".result").fadeIn("slow");
    });
});

$("body").on("click", ".x", function () {
	$(".result").fadeOut("slow");
});

});
```

Damit wird zusätzlich zum eigentlichen Inhalt noch ein "X" in die result-Box geladen. Wenn man auf das X klickt, wird die Box wieder ausgeblendet.


----------



## yuro (13. September 2013)

danke dir tombe. funktioniert perfekt.

Eine Frage nur.. Kann man das nicht auch mit der Funktion removeClass(); machen? oder wofür dient sie genau?

Das prepend() dient nur dazu das der button X vor dem eigentlichen Inhalt steht ne? Man hätte auch wenn es jetzt nicht wichtig ist wo das X stehen soll auch append(); nehmen können oder?


----------



## tombe (13. September 2013)

Die Funktion "load" lädt den kompletten Inhalt der Box neu. Sprich alles was vorher enthalten war ist weg bzw. wird mit dem neuen Inhalt überschrieben

"prepend" ist wie du richtig geschrieben hast dazu da, denn hierbei angegebenen Code als erstes in dem Container zu platzieren. Mit "append" dagegen würde es ganz am Ende stehen.

Mit "removeClass" entfernst du die Klasse, das stimmt auch.
Du müsstest dann aber a) eine andere Klasse dafür aufnehmen und b) würde die Box dann einfach schlagartig verschwinden, so wird sie ausgeblendet.


----------



## yuro (13. September 2013)

Ahhh ok verstehe. Und dann hätte ich noch eine letzte Frage. Muss das "preventDefault()" immer mit dabei sein? Wenn nicht, wann weiss ich wann ich es einsetzen muss?

Achja zu einem CSS-Teil wollt ich auch noch was wissen und zwar klappt meine Navigation einwandfrei mit dem hovern usw. Ich will das wenn du z.b. auf Kontakt klickst und sich der content öffnet soll oben in der Navigation der Menüpunkt Kontakt aktiv sein also das man sieht auf welcher seite man sich befindet, sodass der Hoverzustand bleibt.

Ich dachte immer das funktioniert mit z.B. #menu li:active aber das ging irgendwie nicht.


----------



## tombe (13. September 2013)

Hier steht es (auf englisch) schön beschrieben wann man "event.preventDefault" benötigt und wann nicht:



> The event.preventDefault() method stops the default action of an element from happening.
> 
> For example:
> 
> ...



Also immer dann wenn das Ereignis das normalerweise ausgeführt wird *nicht* eintreten soll, musst du diese Anweisung verwenden!

Um den Link "aktiv" zum machen, benötigst du folgende 2 Zeilen:


```
$(".link").removeClass("active");
$(this).addClass("active");
```

und natürlich die entsprechende CSS Klasse "active".

Hiermit wird zuerst der zuletzt aktive Link wieder auf "normal" gesetzt indem die Klasse gelöscht wird. Dann wird dem Link der angeklickt wurde diese Klasse zugewiesen.


----------



## Jan-Frederik Stieler (18. September 2013)

Hi,
wann nimmt man welche der drei Varianten

```
$("a.link").bind('click', function(e){
```
und

```
$('.filter-table a').click(function(e){
```
und

```
$('.filter-table a').on('click, 'function(e){
```


Bei dieser Variante des Scriptes

```
$(function(){
	$('.filter-table a').click(function(ajaxClick){
		ajaxClick.preventDefault();
		var contentToLoad = $(this).attr('href');
	
		$(".ajaxContent").slideDown('8000', function(){
			$(this).load(contentToLoad, function(){
				$('.ajaxContent').prepend('<button class="btn icon-remove pull-right"></button>');
			});
		});
		$(this).addClass('active');
	});
	
	$('body').on('click', '.icon-remove', function () {
		$('.ajaxContent').children().toggle('slow', function(){
			$(this).slideUp('slow');
		});
	});
});
```
wird .load() doch erst als Callback der slideDown Klasse geladen. 
Der Slide sollte sich ja mit 8000 auch extremst langsam öffnen, macht er aber nicht.
Warum sieht das immer noch so aus als gäbe es keinen Slide?


Grüße


----------

