toggle Box (bitte nur JavaScript, kein jQuery)

B

ByeBye 281348

Guten Abend alle miteinander,

Ich möchte im vorhinein sagen, dass ich die Forumsuche und Googlesuche benutzt habe, aber keine bzw. nur teilweise zufriedenstellende Ergebnisse heraus gekommen sind.

Dass man eine DIV-Box super einfach mit jQuery auf- und zuklappen kann, dass ist mir schon klar, allerdings will ich für mein aktuelles Projekt aufgrund einiger Nachteile von jQuery reines JavaScript verwenden.

Ich möchte eine DIV-Box per Klick auf- und zuklappen lassen. Soweit so gut.
1. Allerdings ist beim auf- und zufahren der Box der Padding von <article> nicht drin. Die Schrift in der <ul> grenzt direkt an der Unterkante des <article>. Kennt jemand eine Lösung, dass der Padding auch beim auf- und zuklappen verhindert, dass die Schrift an die Unterkante grenzt.
2. Ist die Box geöffnet und man macht einen Doppelklick auf die Überschrift, dann flackert/springt die Box kurz und schließt sich dann.
Ist die Box geschlossen und man macht einen Doppelklick auf die Überschrift, dann geht die Box auf, schließt sich aber sofort im nächsten Augenblick wieder ohne lästiges Flackern. Mir geht es primär gar nicht ums Flackern, sondern darum, dass die Box bei einem Doppelklick auf beide Klicks entsprechend reagieren soll: Erster Klick = eine Richtung, zweiter Klick = andere Richtung.
3. Gibt es eine bessere Lösung als CSS-transition, um die Box sliden zu lassen? Also ich ahne schon, aber ich kann sie mit meinem aktuellen Wissen nicht umsetzen.

HTML:
<body>
<article>
   <a href="javascript:toggleBox()"><h2>Ueberschrift</h2></a>
   <a href="javascript:toggleBox()"><h3>Ueberschrift Zeile</h3></a>
       <div id="js_togglebox_1">
           <ul id="js_togglebox_2">
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li>
               <li><a href="#">Listenpunkt</a></li></ul></div></article>
</body>

CSS:
<style>
*{
   font-weight:300;
   margin:0em;
   text-align:center;
   text-decoration:none;
}
body{
   background:#CCC;
}
article{
   background:#FFF;
   border:1px solid #000;
   margin:auto;
   overflow-y:hidden;
   padding:3em;
   width:75%;
}
h2{
   color:#C85A46;
   font-family:"Quicksand";
   font-size:2.5em;
   font-weight:700;
}
h2:hover{
   color:#E87A66;
}
h3{
   color:#5A82C8;
   font-size:2em;
}
h3:hover{
   color:#404040;
}
div{
   line-height:1.5;
}
ul{
   padding:1em 0 0 0;
}
li{
   list-style:none;
}
</style>

Javascript:
<script>
    function toggleBox(step, direction){
       if(direction != 1 && direction != -1){/* create variables */
           if(document.getElementById("js_togglebox_1").style.visibility == "hidden" || document.getElementById("js_togglebox_1").style.height == "0px"){
               direction = 1;/* =positive counter; */
               step = 1;
           }else{
               direction = -1;/* =negative counter; */
               step = 10;
           }
       }

           var maxHeight = document.getElementById("js_togglebox_2").offsetHeight;/* works only by box_2-in-box_1 */
           var currentHeight = maxHeight*(step*10)/100;
           document.getElementById("js_togglebox_1").style.height = currentHeight+"px";/* smooth toggle box_1 */
         

       if((step < 10 && direction == 1) || (step > 0 && direction == -1)){
           toggleBoxTimer = setTimeout("toggleBox(" + (step + direction) + "," + direction + ")", 25);
           document.getElementById("js_togglebox_1").style.transition = "2s";
           document.getElementById("js_togglebox_1").style.visibility = "";
       }

       if(direction < 0 && step <= 0){
           document.getElementById("js_togglebox_1").style.visibility = "hidden";
       }
    }
</script>
 
Hallo SteveRamone,
hast du etwas gegen alle JS Frameworks oder nur Speziell gegen JQuery?

Natürlich ist das auch ohne JS Framework alles möglich, aber man sollte sich auch überlegen, warum sollte man kein Framework einsetzen.
Ein Vorteil ist schon einmal, dass die Funktionen in allen Browsern funktionieren und dies auch immer wieder immer weiter entwickelt wird.
Das müsstest du bei einer selbst entwickelten Funktion auch sicherstellen.

Das ist nicht in jeden Fall sehr einfach besonders wenn man die Kompatibilität gegenüber älteren Browsern noch sicherstellen will.

Zu deinen Fragen es gibt auch andere Möglichkeiten als CSS-Transitions.
Allerdings ist es eine Frage der Performance, man könnte z.B. per JavaScript die Höhe aller x ms vergrößern oder verkleinern.
Aber das birgt auch wieder gefahren, dass Verschiedene Browser unterschiedlich reagieren.

CSS ist ein Standard an denen die verschiedenen Browser probieren sich zu halten und dies wird auch immer besser. Also nutze lieber CSS anstelle von einer JS Funktion, die diese Funktion nachahmt.
 
merzi86,

ich danke Dir für deinen Rat.

Ich muss gestehen, dass ich HTML, CSS, JavaScript, jQuery, PHP erst seit Mitte letzten Monat lerne und noch arg grün hinter den Ohren bin. Das man mit CSS eine auf- und zuklappbare Box erstellen kann ist mir bekannt und habe ich schon durch. Auch sonst weiß ich im groben, bis wohin HTML und CSS reichen können. Ganz anders ist es mit JavaScript. Das beginne ich gerade erst zu verstehen - ganz schön tricky mit den ganzen Verschachtelungen manchmal. AberJavaScript ist eben auch wie ein gutes Sudoku. Und vielleicht geht es mir ein Stück weit darum: Sudoku mal ganz anders. ;)

jQuery ist ein super Framework und ich nutze es auch hier und da mal, wenn etwas zur Präsentation schnell fertig sein soll. Aber jQuery baut eben auch auf JavaScript auf und ich interessiere mich wirklich für die Sprache JavaScript. Und was sich mit jQuery erreichen lässt, lässt sich ja auch mit reinem JavaScript erreichen - nur umständlicher! ;) logisch!

Und ehrlich gesagt: Ich komme so ein bisschen aus der Knöpfchendrücker-Industrie, genannt Industrie 4.0 (Druckindustrie Offset) und Frameworks, so sehr sie ihre Berechtigung auch haben, ohne Frage, haben einige Parallelen zu Knöpfe! Ich mag Knöpfe, sie machen das Leben leichter. Aber manchmal, wenn keine Knöpfe parat sind, muss man sich auch mit den (in gewisser Weise) nächst primitiveren Mitteln auseinandersetzen und sich seine eigenen Knöpfchen herstellen. Ich denke, dass man mit JavaScript noch weiter an die Grenzen gehen kann und letztlich ein größeres Spektrum an Möglichkeiten abdeckt und damit mehr Individualität. Keine Anmache, ich will damit nur mein Bildungsbedürfnis für JavaScript bekunden.

Wenn jemand total gut in JavaScript oder generell Webprogrammierung ist und sich einen Schüler zutraut bzw. ernsthaft mit mir zusammen sich in JavaScript weiterentwickeln möchte, dann kommt mich doch einfach besuchen - ick bin Berliner. Bierchen? :)

Kannst Du mir das mit den "x ms" vielleicht nochmal erklären? Ich hatte mir zur Transition auch überlegt, den Wert der 'var direction' zu ändern, wenn der 'document.getElementById("js_togglebox_2").offsetHeight' eine bestimmte Größe hat. Muss diesen Ansatz aber noch versuchen umzusetzen - bisher hatte ich leider keine Zeit. Vielleicht zerbricht der Ansatz aber auch an meiner Logik. Oder irgendwas wieder mit der Syntax. Ich gebe nicht auf! ^^

Grüßis!
 
Ach das ist dein Ansinnen. :)

Nagut für die die nicht nur "Knöpfchen drücken" wollen gibt es natürlich auch die JavaScript only Variante.

Zunächst erstmal ein bisschen Quellcode:
HTML:
<html>
    <head>
        <script type="text/javascript">
            var transition_running=0;
            var transition_running2=0;

            window.onload = function() {
                var el = document.getElementById("js_transition");
                el.addEventListener("mouseenter", function( ) {
                    transition(this, 300, 1, 5);
                });
             
                el.addEventListener("mouseleave", function( ) {
                    transition(this, 100, -1, 5);
                });
           
                var el = document.getElementById("js_transition2");
                el.addEventListener("dblclick", function( ) {
                    transition2(this, 100, 300, 5, -1);
                });
             
            };
           
            function transition(element, size, direction, shift) {
                transition_running = direction;
             
                if( element.style.width == '' ) {
                    style = window.getComputedStyle(element),
                    element.style.width=style.getPropertyValue('width');
                }
               
                var width=parseInt(element.style.width);
             
                if( (transition_running == 1 && width >= size) ||
                    (transition_running == -1 &&  width <= size) ||
                    transition_running == 0 ) {
                        transition_running=0;
                    return true;
                }
               
                element.style.width=(width+(transition_running*shift))+'px';
                   
                window.setTimeout( function( ){ transition(element, size, direction, shift); }, 1);
            }
           
            function transition2(element, min_size, max_size, shift, toggle) {
                if( element.style.width == '' ) {
                    style = window.getComputedStyle(element),
                    element.style.width=style.getPropertyValue('width');
                }
               
                var width=parseInt(element.style.width);
           
                if( transition_running2 == 0 &&
                    width<=min_size &&
                    toggle == -1 ) {
                        transition_running2=1;
                } else if( transition_running2 == 0 &&
                            width>=max_size &&
                            toggle == -1 ) {
                    transition_running2=-1;
                } else if( toggle == -1 ) {
                    transition_running2=transition_running2*toggle;
                }
               
                if( (transition_running2 == 1 && width >= max_size) ||
                    (transition_running2 == -1 &&  width <= min_size) ||
                    transition_running2 == 0 ) {
                        transition_running=0;
                    return true;
                }
               
                element.style.width= (width+(transition_running2*shift))+'px';
                   
                window.setTimeout( function( ){ transition2(element, min_size, max_size, shift); }, 1);
            }
        </script>
       
        <style>
            div {
             width: 100px;
             height: 100px;
             background: red;
             -webkit-transition: width 2s; /* For Safari 3.1 to 6.0 */
             transition: width 2s;
            }

            div#css_transition:hover {
                width: 300px;
            }

            h1 {
             margin-top:50px; 
            }
        </style>
    </head>
    <body>   
        <h1>JavaScript</h1>
        <div id="js_transition" class="transition">
        </div>
        <h1>CSS</h1>
        <div id="css_transition" class="transition">
        </div>
        <h1>JavaScript Doppelklick</h1>
        <div id="js_transition2" class="transition">
        </div>
    </body>
</html>

So nun zur Erklärung.

Die ersten beiden machen im Prinzip das selbe. Sobald man mit dem Mauszeiger über das Element fährt verändert das Element seine Breite.

Die JavaScript Funktion (transition) ist relativ einfach.
Die ersten 15 Zeilen sind nur für die Vorbereitung, Verallgemeinerung und Änderung des Status zuständig.
So wird eine Richtung angegeben (transition_running), diese beeinflusst das Wachsen oder Schrumpfen des Elements.

In der 17. Zeile der Funktion wird die Größe des Elements geändert. Anschließend wird dem Fenster gesagt warte eine gewisse Zeit. Nach der Wartezeit wird die Funktion selbst wieder aufgerufen.

Das Dritte Beispiel dürfte so sein, wie du es dir vorstellst.
Wenn der Nutzer ein Doppelklick auf das Element Klickt wird die Größe verändert, bis die Endgültige Größe erreicht wird oder bis der nächste Doppelklick ausgelöst wird.

Vom Aufbau her ist die Funktion relativ identisch mit der ersten, nur was das feststellen der Richtung der Veränderung betrifft ist etwas anders.

Diese 2. Funktion ist mit CSS nicht so einfach, da es kein Doubleklick im CSS gibt. Für diese Möglichkeit gibt es höchstens ein paar Workarounds bzw. CSS Hacks.

Ein paar Beispiele für solche Hacks findest du hier: https://css-tricks.com/examples/CSSDoubleClick/

Ein einfacher Klick ist mittels CSS möglich mit dem Selektor :active.

Ich würde dir empfehlen auf Doppelklick soweit zu verzichten, wie es geht, da z.B. auf Smartphones und Tablets dieser nur schwer zu realisieren ist bzw. dieses nirgends Ordentlich genutzt wird und daher die Nutzer das nicht gewohnt sind.

So das waren jetzt erstmal viele Infos.
Ich hoffe ich konnte dir helfen.
Bei Fragen, dann ganz einfach Fragen ;)
 
Wow! Danke für das Script. Sowas beeindruckt mich voll - will das auch so gut können! :)

Ich werde mir deinen Beitrag erst gegen Wochenende so richtig zu Gemüte tun können. Davor erstmal vielleicht ausdrucken und auf den Bahnfahrten etwas anstarren. *hehe*

Have a nice week.
 
Zurück