@@Jnnbo
jQuery ist absolut nicht meine stärke.
Dann nimm’s doch nicht!
Spaß beiseite. Vorerst. Wir kommen drauf zurück.
Hat jemand eine Idee oder ein Stück fertigen Code?
Hab ich jetzt.
Die Idee ist, mit JavaScript keine Darstellung anzugeben.
Ob das Zeug im eingeklappten Zustand gänzlich verschwindet oder verkleinert wird oder (teil)transparent wird, kann JavaScript schnurzpiepegal sein. Mit JavaScript wird lediglich der Zustand hin- und hergeschaltet, bspw. mit einer Klasse am Containerelement.
Markup:
<div class="accordion collapsed">
<button class="ctrl-toggle">
<span class="label-expand">Anwort zeigen</span>
<span class="label-collapse">Anwort verstecken</span>
</button>
<p>Gitarrenlehrer: „Wie nennt man den ersten Finger?“</p>
<p class="details">Kind: „Zeigefinger.“</p>
</div>
Die Anzeige bzw. Nichtanzeige von Elementen regelt das Stylesheet:
.label-expand { display: none }
.accordion.collapsed .label-expand { display: inline }
.accordion.collapsed .label-collapse { display: none }
.accordion.collapsed .details { display: none }
Das einzige, was JavaScript tut, ist die Klasse "collapsed" umzuschalten:
$('.ctrl-toggle').on('click', function ()
{
$(this).closest('.accordion').toggleClass('collapsed');
});
Wie du siest, sind hier keine IDs im Spiel und das Script sucht sich das zum gedrückten .ctrl-toggle
-Button gehörige .accordion
-Vorfahrenelement mittels closest()
.
Das bedeutet, dass es mehrere dieser .accordion
-Elemente mit jeweiligen .ctrl-toggle
-Buttons und .details
-Elementen geben kann.
Beispiel 1 [^1]
Nun stellt sich durchaus die Frage: Braucht man zum simplen Umschalten einer Klasse jQuery?
Nein, moderne Broser können das mit Vanilla-JavaScript[^2]. Das sieht bis auf die in jQuery weggekapselte Schleife fast genauso aus:
var ctrlToggleElements = document.querySelectorAll('.ctrl-toggle');
for (var i = 0, l = ctrlToggleElements.length; i < l; i++)
{
ctrlToggleElements[i].addEventListener('click', function ()
{
this.closest('.accordion').classList.toggle('collapsed');
}, false);
}
(im Beispielquelltext als Kommentar)
Unschön daran ist, dass ohne JavaSript gar nichts geht; die Akkordeons bleiben zu.
Sie müssten also initial offen sein und erst mit JavaScript geschlossen werden. Außerdem machen die Buttons ohne JavaScript keinen Sinn, weshalb sie initial versteckt werden (HTML-Attribut hidden
) und erst mit JavaScript angezeigt werden:
<div class="accordion">
<button class="ctrl-toggle" hidden>
$('.accordion').addClass('collapsed');
$('.ctrl-toggle').removeAttr('hidden').on('click', function ()
{
$(this).closest('.accordion').toggleClass('collapsed');
});
.removeAttr('hidden')
und .on('click', …)
kann man in jQuery direkt aneinanderhängen (chaining).
Und so funktioniert das ganze auch ohne JavaScript: Alles wird angezeigt. JavaScript ist progressive enhancement. (Sollte es immer sein.)
Beispiel 2
Nun wirst du sagen: Ich wollte doch animiert auf- und zuklappen. Kannst du haben: mit CSS-Transitions.
Beispiel 3
Man kann nun nicht height
zwischen 0
und auto
animieren, sondern nur zwischen zwei Zahlenwerten. Da die Höhe unbekannt ist, wird max-height
zwischen 0
und einem hinreichend großen Wert (im Beispiel 4em
) animiert.
Das hat zur Folge, dass beim Zuklappen die sichtbare Animation nicht sofort nach dem Drücken des Button erfolgt, d.h. dass der Nutzer kein sofortiges Feedback zu seiner Aktion erhält. Unschön.
Abhilfe könnte sein, mit JavaScript die Höhe des gerenderten (geöffneten) .details
-Elements auszulesen und dann zwischen 0
und diesem Wert zu animieren.
Ich hab das jetzt nicht mit einem Screenreader getestet. Aber interessant dürfte sein, was letztens über den Ticker lief.
LLAP
--
„Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
[^1]: Die Bespieltexte sind
nicht von mir ausgedacht.
[^2]: Wer hat sich eigentlich die Bezeichnung „Vanilla“ ausgedacht?