mely: Javascript fehler

Hallo,

ich habe folgendes Problem: Wenn ich die Seite durchscrolle, ändert sich die Farbe von dem Link im Menü. Äbhängig wo man sich befindet bleibt der Menüpunkt grün. Alle anderen sind grau. Das gleiche soll auch passieren wenn man auf das Menüpunkt klickt. Also die Aktuelle link wird grün und alle anderen bleiben grau. Klickt man auf ein anderen Menüpunkt wird er grün und alle anderen wieder grau. In meinem script.js(ganz unten im quelltext) ist wahrschinlich was falsches eingegeben, da nicht bei jedes Menüklick bleib er grün. Ich habe die Fehler viel gesucht, aber nicht gefunden. Kann mir jemand helfen. Danke im voraus Linkbeschreibung

Das ist ein Teil von script.js und ich glaube die Fehler ist hier irgendwo. Kann das sein?

$('nav a[href^="#"]').on('click', function (e) {
                        e.preventDefault();
                        $(document).off("scroll");
 
                       $('nav a').each(function () {
                                $(this).removeClass('active');
                                 $("nav").removeClass("navTest");
                        })
                        $(this).addClass('active');
 
                        var target = this.hash;
                        $target = $(target);
                        $('html, body').stop().animate({
                                'scrollTop': $target.offset().top+2
                        }, 500, 'swing', function () {
                                window.location.hash = target;
                                $(document).on("scroll", onScroll);
                        });
                });
        });
 
        function onScroll(event){
                var scrollPosition = $(document).scrollTop();
                $('nav a').each(function () {
                        var currentLink = $(this);
                        var refElement = $(currentLink.attr("href"));
                        if (refElement.position().top <= scrollPosition && refElement.position().top + refElement.height() > scrollPosition) {
                                $('nav ul li a').removeClass("active");
                                currentLink.addClass("active");
                        }
                        else{
                                currentLink.removeClass("active");
                        }
                });

Grüße

akzeptierte Antworten

  1. Hallo,

    so auf die Schnelle sehe ich das ein }); zuviel war, ob das aber der Fehler war?

    $('nav a[href^="#"]').on('click', function (e) {
       e.preventDefault();
       $(document).off('scroll');
       $('a').each(function () {
          $(this).removeClass('active');
       })
       $(this).addClass('active');
       var target = this.hash;
       $target = $(target);
       $('html, body').stop().animate({
          'scrollTop': $target.offset().top+2
          }, 500, 'swing', function () {
             window.location.hash = target;
             $(document).on('scroll', onScroll);
          });
    });
    

    gruesse november

    1. Hallo,

      so auf die Schnelle sehe ich das ein }); zuviel war, ob das aber der Fehler war?

      Hallo November, nein, die Klammer ist nicht zu viel, da ich nur ein Teil von mein script veröffentlicht habe und deswegen saß es nur so aus. Vielen Dank, aber trotzdem für dein Antwort. grüße, mely

      $('nav a[href^="#"]').on('click', function (e) {
         e.preventDefault();
         $(document).off('scroll');
         $('a').each(function () {
            $(this).removeClass('active');
         })
         $(this).addClass('active');
         var target = this.hash;
         $target = $(target);
         $('html, body').stop().animate({
            'scrollTop': $target.offset().top+2
            }, 500, 'swing', function () {
               window.location.hash = target;
               $(document).on('scroll', onScroll);
            });
      });
      

      gruesse november

  2. Hallo Mely

    Bin etwas zu müde um mir das jetzt genauer anzuschauen, aber du könntest mal folgendes versuchen:

    • In der Zeile 'scrollTop': $target.offset().top+2 die ‚+2‘ am Ende rausnehmen, und

    • in der Funktion onScroll die Anweisung else { currentLink.removeClass("active"); } löschen.

    Viele Grüße,

    Orlok

    1. Hallo Mely

      Bin etwas zu müde um mir das jetzt genauer anzuschauen, aber du könntest mal folgendes versuchen:

      • In der Zeile 'scrollTop': $target.offset().top+2 die ‚+2‘ am Ende rausnehmen, und

      • in der Funktion onScroll die Anweisung else { currentLink.removeClass("active"); } löschen.

      Hallo Orlok,

      es hat funktioniert mit deine Anweisungen. Vielen Dank :) Ich verstehe nur nicht wie kommst du darauf. Kannst du es mir kurz erklären. Danke im voraus.

      Grüße, mely

      Viele Grüße,

      Orlok

    2. Hallo Mely

      Bin etwas zu müde um mir das jetzt genauer anzuschauen, aber du könntest mal folgendes versuchen:

      • In der Zeile 'scrollTop': $target.offset().top+2 die ‚+2‘ am Ende rausnehmen, und

      • in der Funktion onScroll die Anweisung else { currentLink.removeClass("active"); } löschen.

      Hallo, gerade merke ich, dass das Problem ist zwar behoben, aber dass es neue Problem dadurch entsteht. Und zwar, dass wenn man die Seite neuladet mit F5 die Seite bleibt wo sie war, aber die Linkfarbe springt zu der Start siehe Linkbeschreibung.

      Grüße

      Viele Grüße,

      Orlok

      1. Hallo Mely

        Erstmal sorry, dass ich auf deine andere Frage bisher noch nicht geantwortet habe. ;-)

        Du wolltest wissen, wie ich darauf gekommen bin, dass das Problem mit den von mir genannten Anweisungen zusammenhängen könnte…

        Naja, da gibt es nicht viel dazu zu sagen:

        • Die zu dem Wert von $target.offset( ).top hinzugezählten ‚+2‘ wurden in deiner Funktion onScroll nicht berücksichtigt und erschienen mir davon abgesehen auch grundsätzlich sinnlos.

        • Die else-Anweisung wiederum schien auf den ersten Blick die einzig logische Ursache dafür zu sein, dass das mit der Link-Farbe nicht funktioniert hat, denn in deinem click-Handler hattest du ja die Anweisung $(this).addClass('active') notiert, die eigentlich dafür sorgen sollte, dass der Link auch entsprechend eingefärbt wird. Es musste darum an deinem scroll-Handler liegen, der jedesmal (else), wenn die if-Bedingung nicht greift, automatisch die Klasse (und somit die Farbe) weggenommen hat.

        Gerade merke ich, dass das Problem ist zwar behoben, aber dass es neue Problem dadurch entsteht. Und zwar, dass wenn man die Seite neuladet mit F5 die Seite bleibt wo sie war, aber die Linkfarbe springt zu der Start.

        Dass die Seite beim Neuladen an der Stelle bleibt wo sie war, dürfte am Browser liegen, der es sich gewissermaßen merkt, bis wohin die Seite gescrollt war. – „It's not a bug, it's a feature!“

        Nun hast du aber in deinem HTML die Zeile <a href="#index" class="active">Start</a>, die dafür sorgt, dass zunächst mal der erste Link in deinem Menü eingefärbt ist – was an und für sich auch sinnvoll ist, aber hier nun dazu führt, dass die Position in der Seite nach dem Neuladen mit der Link-Farbe nicht mehr übereinstimmt.

        Du könntest nun natürlich erzwingen, dass die Seite nach dem Laden automatisch an den Anfang springt, wenn sie dort nicht schon ist, aber ich glaube es wäre besser, einfach die Farbe der Links entsprechend anzupassen.

        Dazu bräuchtest du denke ich im Grunde nur beim Start die Funktion onScroll manuell aufrufen, wobei du diesen Aufruf in deine Handlerfunktion für DOMContentLoaded integrieren könntest:

        document.addEventListener('DOMContentLoaded', function ( ) {
          onScroll( ); // <-- manueller Aufruf beim Start
          if (window.innerWidth < 500) {
            var a = document.querySelectorAll('a.fancybox');
            var len = a.length, i;
            for (i = 0; i < len; i += 1) {
              a[i].removeAttribute('class');
              a[i].removeAttribute('href');
            }
          }
        });
        

        Habe es natürlich nicht getestet, aber das sollte funktionieren. ;-)

        Viele Grüße,

        Orlok

        1. Hallo Mely

          Erstmal sorry, dass ich auf deine andere Frage bisher noch nicht geantwortet habe. ;-)

          Hallo, kein Problem :)

          Du wolltest wissen, wie ich darauf gekommen bin, dass das Problem mit den von mir genannten Anweisungen zusammenhängen könnte…

          Naja, da gibt es nicht viel dazu zu sagen:

          • Die zu dem Wert von $target.offset( ).top hinzugezählten ‚+2‘ wurden in deiner Funktion onScroll nicht berücksichtigt und erschienen mir davon abgesehen auch grundsätzlich sinnlos.

          • Die else-Anweisung wiederum schien auf den ersten Blick die einzig logische Ursache dafür zu sein, dass das mit der Link-Farbe nicht funktioniert hat, denn in deinem click-Handler hattest du ja die Anweisung $(this).addClass('active') notiert, die eigentlich dafür sorgen sollte, dass der Link auch entsprechend eingefärbt wird. Es musste darum an deinem scroll-Handler liegen, der jedesmal (else), wenn die if-Bedingung nicht greift, automatisch die Klasse (und somit die Farbe) weggenommen hat.

          Gerade merke ich, dass das Problem ist zwar behoben, aber dass es neue Problem dadurch entsteht. Und zwar, dass wenn man die Seite neuladet mit F5 die Seite bleibt wo sie war, aber die Linkfarbe springt zu der Start.

          Dass die Seite beim Neuladen an der Stelle bleibt wo sie war, dürfte am Browser liegen, der es sich gewissermaßen merkt, bis wohin die Seite gescrollt war. – „It's not a bug, it's a feature!“

          Nun hast du aber in deinem HTML die Zeile <a href="#index" class="active">Start</a>, die dafür sorgt, dass zunächst mal der erste Link in deinem Menü eingefärbt ist – was an und für sich auch sinnvoll ist, aber hier nun dazu führt, dass die Position in der Seite nach dem Neuladen mit der Link-Farbe nicht mehr übereinstimmt.

          Du könntest nun natürlich erzwingen, dass die Seite nach dem Laden automatisch an den Anfang springt, wenn sie dort nicht schon ist, aber ich glaube es wäre besser, einfach die Farbe der Links entsprechend anzupassen.

          Dazu bräuchtest du denke ich im Grunde nur beim Start die Funktion onScroll manuell aufrufen, wobei du diesen Aufruf in deine Handlerfunktion für DOMContentLoaded integrieren könntest:

          document.addEventListener('DOMContentLoaded', function ( ) {
            onScroll( ); // <-- manueller Aufruf beim Start
            if (window.innerWidth < 500) {
              var a = document.querySelectorAll('a.fancybox');
              var len = a.length, i;
              for (i = 0; i < len; i += 1) {
                a[i].removeAttribute('class');
                a[i].removeAttribute('href');
              }
            }
          });
          

          Habe es natürlich nicht getestet, aber das sollte funktionieren. ;-)

          Ich habe die onScroll manuel hinzugefügt, aber iwie ist er wieder nicht ganz richtig. Er springt sogar manchmal in der falsche Stelle z.B wenn ich auf Test4 Linkmenü klicke er springt dahin, macht er aber die Linkfarbe bei Test3 grün. Und er springt immer noch manchmal zu Anfang siehe Linkbeschreibung

          Grüße, mely

          Viele Grüße,

          Orlok

          1. Hallo @mely

            Ich habe die onScroll manuell hinzugefügt, aber irgendwie ist er wieder nicht ganz richtig. Er springt sogar manchmal in der falsche Stelle z.B wenn ich auf Test4 Linkmenü klicke er springt dahin, macht er aber die Linkfarbe bei Test3 grün. Und er springt immer noch manchmal zu Anfang siehe Linkbeschreibung

            Also. Zunächst mal wäre es wahrscheinlich eine gute Sache, statt die Funktion onScroll nach dem Laden des Dokumentes immer auszuführen, dies nur zu tun, wenn die Seite auch tatsächlich neu geladen und vom Browser automatisch gescrollt wurde, weshalb du es vielleicht besser so schreiben solltest:

            document.addEventListener('DOMContentLoaded', function ( ) {
              if (document.documentElement.scrollTop !== 0) {
                onScroll( );
              }
              // ...
            });
            

            Davon abgesehen würde ich empfehlen zu versuchen, die if-Bedingung in deiner Funktion onScroll mal anders zu formulieren:

            if (refElement.offset( ).top <= scrollPosition + 5) {
              $('nav ul li a').removeClass('active');
              currentLink.addClass('active');
            }
            

            Das sieht zwar nicht besonders elegant aus, sollte jetzt aber eigentlich funktionieren, und was den Unterschied zwischen offset() und position() angeht, könntest du zum Beispiel hier mal nachsehen.

            Darüber hinaus ist mir auch aufgefallen, dass du in deinem click-Handler noch eine globale Variable produzierst, wo du eigentlich überhaupt keine Variable bräuchtest:

            $target = $(target);
            

            Die Zeile kannst du eigentlich löschen und dann bei der Wertzuweisung zwei Zeilen weiter unten direkt Folgendes schreiben:

            'scrollTop' : $(target).offset( ).top
            

            Schließlich noch ein kleiner Hinweis zu deiner Antwort: Bitte versuche in Zukunft Vollzitate zu vermeiden und nur die Teile zu zitieren, auf die du dich auch wirklich beziehst. ;-)

            Viele Grüße,

            Orlok

            1. Hallo @mely

              Ich habe die onScroll manuell hinzugefügt, aber irgendwie ist er wieder nicht ganz richtig. Er springt sogar manchmal in der falsche Stelle z.B wenn ich auf Test4 Linkmenü klicke er springt dahin, macht er aber die Linkfarbe bei Test3 grün. Und er springt immer noch manchmal zu Anfang siehe Linkbeschreibung

              Also. Zunächst mal wäre es wahrscheinlich eine gute Sache, statt die Funktion onScroll nach dem Laden des Dokumentes immer auszuführen, dies nur zu tun, wenn die Seite auch tatsächlich neu geladen und vom Browser automatisch gescrollt wurde, weshalb du es vielleicht besser so schreiben solltest:

              document.addEventListener('DOMContentLoaded', function ( ) {
                if (document.documentElement.scrollTop !== 0) {
                  onScroll( );
                }
                // ...
              });
              

              Davon abgesehen würde ich empfehlen zu versuchen, die if-Bedingung in deiner Funktion onScroll mal anders zu formulieren:

              if (refElement.offset( ).top <= scrollPosition + 5) {
                $('nav ul li a').removeClass('active');
                currentLink.addClass('active');
              }
              

              Das sieht zwar nicht besonders elegant aus, sollte jetzt aber eigentlich funktionieren, und was den Unterschied zwischen offset() und position() angeht, könntest du zum Beispiel hier mal nachsehen.

              Darüber hinaus ist mir auch aufgefallen, dass du in deinem click-Handler noch eine globale Variable produzierst, wo du eigentlich überhaupt keine Variable bräuchtest:

              $target = $(target);
              

              Die Zeile kannst du eigentlich löschen und dann bei der Wertzuweisung zwei Zeilen weiter unten direkt Folgendes schreiben:

              'scrollTop' : $(target).offset( ).top
              

              Schließlich noch ein kleiner Hinweis zu deiner Antwort: Bitte versuche in Zukunft Vollzitate zu vermeiden und nur die Teile zu zitieren, auf die du dich auch wirklich beziehst. ;-)

              Hallo Orlok,

              vielen Dank für dein Antwort. Ersmal es hat geklappt, verursacht aber andere Fehler siehe hier. Und was meintest du unter Vollzitate zu vermeiden? Ich verstehe es nicht.

              Grüße, mely

              Viele Grüße,

              Orlok

              1. Hallo mely

                vielen Dank für dein Antwort. Ersmal es hat geklappt, verursacht aber andere Fehler siehe hier.

                Du hast mich hier gleich zweimal falsch verstanden. ;-)

                Zunächst einmal hast du zwar wie von mir empfohlen die Zeile $target = $(target); gelöscht, dann aber vergessen, die Zuweisung zwei Zeilen weiter unten auch anzupassen:

                'scrollTop' : $(target).offset( ).top // und nicht $target.offset( ).top ! :-)
                

                Dazu hast du in deiner Handlerfunktion für DOMContentLoaded die if-Anweisung die da vorher drin stand gelöscht und alles in den Block der neuen Anweisung geschrieben, aber ich meinte, dass du nur den Funktionsaufruf von onScroll von der Bedingung abhängig machen solltest, dass die Seite nach dem Neuladen automatisch gescrollt wurde:

                document.addEventListener('DOMContentLoaded', function ( ) {
                  if (document.documentElement.scrollTop !== 0) {
                    onScroll( );
                  }
                  if (window.innerWidth < 500) {
                    var a = document.querySelectorAll('a.fancybox');
                    var len = a.length, i;
                    for (i = 0; i < len; i += 1) {
                      a[i].removeAttribute('class');
                      a[i].removeAttribute('href');
                    }
                  }
                });
                

                Der andere if-Anweisung kann doch ruhig so bleiben wie sie war, das ist ja eine andere Baustelle.

                Und was meintest du unter Vollzitate zu vermeiden? Ich verstehe es nicht.

                Du zitierst immer den kompletten Beitrag, auf den du antwortest. Das nennt man ‚Vollzitat‘ und das erschwert das Lesen deiner Beiträge, also bitte vermeide das, indem du die Teile des Beitrags, auf die du dich nicht konkret beziehst, aus deiner Antwort löschst, so wie ich hier in diesem Beitrag ja auch nur einen bestimmten Teil deines Beitrags zitiere. ;-)

                Viele Grüße,

                Orlok

                1. Hallo mely

                  vielen Dank für dein Antwort. Ersmal es hat geklappt, verursacht aber andere Fehler siehe hier.

                  Du hast mich hier gleich zweimal falsch verstanden. ;-)

                  Zunächst einmal hast du zwar wie von mir empfohlen die Zeile $target = $(target); gelöscht, dann aber vergessen, die Zuweisung zwei Zeilen weiter unten auch anzupassen:

                  'scrollTop' : $(target).offset( ).top // und nicht $target.offset( ).top ! :-)
                  

                  Hallo, ich schäme mich eigentlich nochmal zu fragen, aber die Zeile

                  
                  > 'scrollTop' : $(target).offset( ).top 
                  > ~~~
                  
                  ist/war genau so und habe da nichts verändert. Das ganze sieht so aus:
                  
                  ~~~js
                  $(document).ready(function () {
                  
                  $(document).ready(function ( ) {
                    $(".fancybox").fancybox({
                      helpers : {
                        overlay : {
                          locked : false
                        }
                      }
                    });        
                    $(".fancybox").on("click", function ( ) {
                      $(".fancybox").fancybox({
                        openEffect : 'none',
                        closeEffect : 'none'
                      });
                    });
                  });
                  
                      
                        $("#mobile-icon").click(function(){
                          $("nav").addClass("navTest");
                      });
                  $(".zoom-demo").spritezoom({
                  					fadeInSpeed  : 200,
                  					fadeOutSpeed : 100,  // general element fade out speed
                  					behavior     : "hover", 
                  					// "inner", "top", "right", "bottom", "left", "magnify" or empty
                  					layout       : "magnify",
                  					// magnifying glass appearance
                  					border       : 4,
                  					magSize      : 0.8,
                  					}); 
                          $(document).on("scroll", onScroll);
                         
                          $('nav a[href^="#"]').on('click', function (e) {
                                          e.preventDefault();
                                          $(document).off("scroll");
                   
                                         $('nav a').each(function () {
                                                  $(this).removeClass('active');
                                                   $("nav").removeClass("navTest");
                                          })
                                          $(this).addClass('active');
                   
                                          var target = this.hash;
                                          $('html, body').stop().animate({
                                                  'scrollTop': $target.offset().top
                                          }, 500, 'swing', function () {
                                                  window.location.hash = target;
                                                  $(document).on("scroll", onScroll);
                                          });
                                  });
                          });
                   
                          function onScroll(event){
                                  var scrollPosition = $(document).scrollTop();
                                  $('nav a').each(function () {
                                          var currentLink = $(this);
                                          var refElement = $(currentLink.attr("href"));
                                           if (refElement.offset().top <= scrollPosition + 5) {
                                                  $('nav ul li a').removeClass("active");
                                                  currentLink.addClass("active");
                                          }
                                  });
                  }
                  
                  document.addEventListener('DOMContentLoaded', function ( ) {
                  	if (document.documentElement.scrollTop !== 0) {
                      onScroll( );
                    }
                    if (window.innerWidth < 500) {
                      var a = document.querySelectorAll('a.fancybox');
                      var len = a.length, i;
                      for (i = 0; i < len; i += 1) {
                        a[i].removeAttribute('class');
                        a[i].removeAttribute('href');
                      }
                    }
                  });
                  

                  Dazu hast du in deiner Handlerfunktion für DOMContentLoaded die if-Anweisung die da vorher drin stand gelöscht und alles in den Block der neuen Anweisung geschrieben, aber ich meinte, dass du nur den Funktionsaufruf von onScroll von der Bedingung abhängig machen solltest, dass die Seite nach dem Neuladen automatisch gescrollt wurde:

                  document.addEventListener('DOMContentLoaded', function ( ) {
                    if (document.documentElement.scrollTop !== 0) {
                      onScroll( );
                    }
                    if (window.innerWidth < 500) {
                      var a = document.querySelectorAll('a.fancybox');
                      var len = a.length, i;
                      for (i = 0; i < len; i += 1) {
                        a[i].removeAttribute('class');
                        a[i].removeAttribute('href');
                      }
                    }
                  });
                  

                  hier habe dich ja ganz falsch verstanden:/

                  Der andere if-Anweisung kann doch ruhig so bleiben wie sie war, das ist ja eine andere Baustelle.

                  Und was meintest du unter Vollzitate zu vermeiden? Ich verstehe es nicht.

                  Du zitierst immer den kompletten Beitrag, auf den du antwortest. Das nennt man ‚Vollzitat‘ und das erschwert das Lesen deiner Beiträge, also bitte vermeide das, indem du die Teile des Beitrags, auf die du dich nicht konkret beziehst, aus deiner Antwort löschst, so wie ich hier in diesem Beitrag ja auch nur einen bestimmten Teil deines Beitrags zitiere. ;-)

                  Ok, ich versuche es zu ändern :)

                  Viele Grüße,

                  Orlok

                  1. Hallo mely

                    Ich schäme mich eigentlich nochmal zu fragen, aber die Zeile

                    'scrollTop' : $(target).offset( ).top 
                    

                    ist/war genau so und habe da nichts verändert.

                    Schämen musst du dich für überhaupt nichts! Aber schau doch noch mal genau hin. :-)

                    Das ganze sieht so aus:

                    // ...
                    
                    $('nav a[href^="#"]').on('click', function (e) {
                      e.preventDefault();
                      $(document).off("scroll");
                      
                      $('nav a').each(function () {
                        $(this).removeClass('active');
                        $("nav").removeClass("navTest");
                      })  // Semikolon vergessen → besser }); als nur })
                    
                      $(this).addClass('active');
                     
                      var target = this.hash;
                      $('html, body').stop().animate({
                        'scrollTop': $target.offset().top // Klammern vergessen → $(target).offset().top
                      }, 500, 'swing', function () {
                        window.location.hash = target;
                        $(document).on("scroll", onScroll);
                      });
                    });
                    
                    // ...
                    

                    Habe den Code mal ein wenig formatiert und die unwichtigen Teile rausgenommen.

                    Du hast bei der Zuweisung die Klammern vergessen: $(target)$target

                    'scrollTop' : $(target).offset().top // → soll es heißen! ;-)
                    

                    Gruß,

                    Orlok

                    1. Hallo mely

                      Ich schäme mich eigentlich nochmal zu fragen, aber die Zeile

                      'scrollTop' : $(target).offset( ).top 
                      

                      ist/war genau so und habe da nichts verändert.

                      Schämen musst du dich für überhaupt nichts! Aber schau doch noch mal genau hin. :-)

                      Das ganze sieht so aus:

                      // ...
                      
                      $('nav a[href^="#"]').on('click', function (e) {
                        e.preventDefault();
                        $(document).off("scroll");
                        
                        $('nav a').each(function () {
                          $(this).removeClass('active');
                          $("nav").removeClass("navTest");
                        })  // Semikolon vergessen → besser }); als nur })
                      
                        $(this).addClass('active');
                       
                        var target = this.hash;
                        $('html, body').stop().animate({
                          'scrollTop': $target.offset().top // Klammern vergessen → $(target).offset().top
                        }, 500, 'swing', function () {
                          window.location.hash = target;
                          $(document).on("scroll", onScroll);
                        });
                      });
                      
                      // ...
                      

                      Habe den Code mal ein wenig formatiert und die unwichtigen Teile rausgenommen.

                      Hey, vielen Dank. Ich habe die Klammer wirklich übersehen.

                      Du hast bei der Zuweisung die Klammern vergessen: $(target)$target

                      Ich bin noch nicht ganz gut in javascript und verstehe die Unterschied nicht. Kannst du es bitte kurz erklären. Danke

                      'scrollTop' : $(target).offset().top // → soll es heißen! ;-)
                      

                      Gruß,

                      Orlok

                      1. Tach,

                        Du hast bei der Zuweisung die Klammern vergessen: $(target)$target

                        Ich bin noch nicht ganz gut in javascript und verstehe die Unterschied nicht. Kannst du es bitte kurz erklären. Danke

                        du hast einmal die Variable namens $target und dann hast du ein Object, das eigentlich jQuery (andere Frameworks machen das ähnlich) heißt, aber meistens über den kürzeren Namen $ angesprochen wird und dem target als Parameter übergeben wird $(target) kurz für jQuery(target).

                        mfg
                        Woodfighter

                      2. Hallo mely

                        Du hast bei der Zuweisung die Klammern vergessen: $(target)$target

                        Ich bin noch nicht ganz gut in javascript und verstehe den Unterschied nicht.

                        Kein Problem.

                        Kannst du es bitte kurz erklären. Danke.

                        Ich kann es zumindest mal versuchen. :-)


                        Also, kurz gesagt, handelt es sich bei $(target) um den Aufruf einer Funktion namens $, bei welchem der Wert der zuvor definierten Variable mit dem Bezeichner target als Argument übergeben wird.

                        Die Angabe $target wiederum ist in diesem Zusammenhang der Versuch, über diesen Bezeichner eine zuvor nicht deklarierte Variable zu referenzieren.


                        Alles klar? Nein? – Ok.

                        Dann versuchen wir es lieber nochmal etwas ausführlicher! ;-)

                        Am besten schauen wir uns zunächst einmal den Teil deines Codes an um den es geht, und zwar in seiner ursprünglichen Form, bevor wir hier die in dieser Hinsicht relevanten Veränderungen vorgenommen haben:

                        $('nav a[href^="#"]').on('click', function (e) {
                          e.preventDefault();
                        
                          // Die an dieser Stelle unwichtigen Anweisungen lasse ich mal weg…
                        
                          var target = this.hash;
                          $target = $(target);
                        
                          $('html, body').stop().animate({
                            'scrollTop' : $target.offset().top
                          }, 500, 'swing', function () {
                            window.location.hash = target;
                            $(document).on('scroll', onScroll);
                          });
                        });
                        

                        Wie woodfighter bereits sagte, ist das Dollarzeichen, also $, kein Teil der Syntax von Javascript, sondern ein Bezeichner, also ein Name, über den jQuery angesprochen werden kann, also im Prinzip nichts anderes als wenn du selbst schreiben würdest:

                        function $ () {
                          // irgendwelche Anweisungen
                        };
                        

                        Das bedeutet, $() ist einfach nur der Aufruf einer Funktion. Wobei eine Funktion auch mit Argumenten aufgerufen werden kann, welche dann innerhalb der runden Klammern notiert werden, mit denen du dem Browser sagst, dass die Funktion aufgerufen werden soll.

                        Stellen wir uns nur so als Beispiel einmal vor, wir hätten eine Funktion mit zwei Parametern notiert, a und b, und dem Bezeichner add, dann könnte das so aussehen:

                        // Beispiel für Funktion mit Parametern
                        
                        function add (a, b) {
                          return a + b;
                        };
                        

                        Diese Funktion könnten wir nun aufrufen, indem wir zunächst den Bezeichner der Funktion notieren, also den Namen add, den wir ihr gegeben haben, und danach ein paar runde Klammern, mit denen wir unseren Wunsch zum Ausdruck bringen, dass die Funktion jetzt aufgerufen werden soll.

                        Innerhalb dieser runden Klammern notieren wir nun durch Komma getrennt zwei Werte, das heißt, wir rufen die Funktion mit zwei Argumenten auf, und den Rückgabewert der Funktion, also das Ergebnis der Addition, die wir nach der return-Anweisung aufgeschrieben haben, speichern wir in einer Variable mit dem Bezeichner c:

                        // Beispiel für Funktionsaufruf mit Argumenten
                        
                        var c = add(3, 5);
                        

                        In der Variable mit dem Bezeichner c wäre nun also der Wert 8 gespeichert, da innerhalb unserer Funktion add die beiden Parameter mit den beim Aufruf der Funktion übergebenen Argumenten initialisiert werden, also a mit 3 und b mit 5.

                        Wenn wir nun also zu deinem Code zurückkommen, sehen wir, dass du innerhalb deiner anonymen, also namenlosen Funktion, die du der jQuery-Methode ‚on‘ als zweites Argument nach 'click' übergibst, die Anweisung var target = this.hash notiert hast.

                        Ohne an dieser Stelle zu weit abschweifen zu wollen sei gesagt, dass die Funktionsvariable this innerhalb dieser Funktion bei ihrem Aufruf mit dem Link initialisiert wird, auf den geklickt wurde, beziehungsweise mit dem Objekt, welches dieses Link-Element repräsentiert.

                        In der Variable mit dem Bezeichner target wird also der Wert der Objekteigenschaft hash hinterlegt, der hier identisch ist mit dem in deinem Markup angegebenen Wert des Attributes href. Also, um das nochmal zu verdeutlichen – du hast in deinem Markup folgenden internen Link…

                        <a href="#test1">Nav - Test 1</a>
                        

                        …und über jQuery hast du nun eine Ereignisüberwachung für deine Links und den Ereignistyp ‚click‘ implementiert, das heißt, sollte jemand nun auf diesen Link klicken, dann würde in der Variable target der String '#test1' gespeichert werden. Und diesen String übergibst du nun jQuery, indem du schreibst…

                        $(target)
                        

                        …damit jQuery dir anhand der ID das Element heraussucht, welches das Ziel (target) deines Links ist, und dir ein Objekt zurückgibt, auf welchem du von jQuery bereitgestellte Methoden anwenden kannst, wie beispielsweise offset(), welche selbst wiederum ein Objekt mit Eigenschaften wie etwa top zurückgibt, deren Wert in diesem Teil deines Codes dann zugewiesen wird (oder werden sollte):

                        'scrollTop' : $(target).offset().top
                        

                        Du hast das mit den Objekten noch nicht so ganz verstanden?


                        Kein Problem. ;-)

                        Ein plain object, also ein ‚normales‘ Objekt wenn man so will, ist eine Datenstruktur, sprich es ist ein Container für Eigenschaften und Methoden, welcher aus Schlüssel/Wert-Paaren besteht, wobei von einer Methode gesprochen wird, wenn es sich bei dem Wert der Eigenschaft um eine Funktion handelt.

                        Es gibt nun verschiedene Möglichkeiten ein solches Objekt zu erzeugen, aber am besten sollte dies über die sogenannte Literalnotation geschehen:

                        var object = {
                          property : 'value',
                          method : function () {
                            return this.property;
                          }
                        };
                        

                        Hier haben wir also zunächst einmal eine Variable mit dem Bezeichner object deklariert und diese zugleich auf definiert, indem wir ihr ein neu erstelltes Objekt als Wert zugewiesen haben.

                        Die Syntax zur Erzeugung eines Objektes besteht also darin, zwischen zwei geschweiften Klammern und durch Kommas getrennt die Eigenschaften aufzulisten, wobei der Bezeichner, also der Name der Eigenschaft zuerst notiert wird, dann ein Doppelpunkt, und dann der Wert, den die Eigenschaft haben soll.

                        In unserem Beispiel object haben wir nun zwei Eigenschaften hinterlegt, wobei eine davon als Wert eine Funktion hat, so dass wir hier von einer Methode sprechen. Innerhalb dieser Funktion verweist bei ihrem Aufruf die Variable this nun auf das Objekt selbst, so dass der Wert der ersten Eigenschaft mit den Namen property zurückgegeben wird, also der String 'value'.

                        Wenn man also ein Objekt erstellt hat, dann gibt es zwei Wege, um auf dessen Eigenschaften zuzugreifen, nämlich entweder über die Punktnotation oder über die Klammernotation:

                        var myValue = object.property;
                        
                        // ist also das gleiche wie:
                        
                        var myValue = object['property'];
                        

                        In beiden Fällen wäre nun der Wert der Eigenschaft property in der Variable mit dem Bezeichner myValue hinterlegt. Aber, auch wenn beide Varianten funktionieren, sollte der besseren Lesbarkeit wegen wenn möglich die Punktnotation verwendet werden. ;-)

                        Jedenfalls kann ein Objekt natürlich nicht nur als Wert einer Variable hinterlegt werden, sondern es kann auch direkt beim Aufruf einer Funktion notiert werden, wie zum Beispiel bei folgendem Methodenaufruf, den ich mal deiner Datei script.js entnommen habe:

                        $(".zoom-demo").spritezoom({
                          fadeInSpeed : 200,
                          fadeOutSpeed : 100,
                          behavior : "hover",
                          layout : "magnify",
                          border : 4,
                          magSize : 0.8
                        }); 
                        

                        Das ist eine sehr nützliche Möglichkeit, um einer Funktion bei ihrem Aufruf Werte mitzugeben, insbesondere dann, wenn sehr viele Parameter benötigt werden, denn sonst müsste man sich immer die genaue Reihenfolge merken, in der die Argumente zu übergeben sind. So übergibt man nur ein Objekt, also ein Argument, und innerhalb der Funktion können dann die einzelnen Eigenschaftswerte ausgelesen werden.

                        Andersherum kann ein Objekt natürlich auch der Rückgabewert einer Funktion sein, was zum Beispiel so umgesetzt werden kann:

                        var getObject = function () {
                          return {
                            a : 1,
                            b : 2,
                            c : 3
                          };
                        };
                        

                        Dabei ist allerdings zu beachten, dass die öffnende geschweifte Klammer für das Objekt in der selben Zeile wie die return-Anweisung stehen muss, da sonst durch die automatische Einfügung eines Semikolons die Ausführung der Funktion nach dieser Anweisung abgebrochen würde und der Code mit dem Objekt nicht mehr erreicht würde.

                        Das nur nebenbei bemerkt. ;-)


                        Aber kommen wir wieder zurück zu deinem ursprünglichen Code:

                          // ...
                          $target = $(target);
                          // ...
                          'scrollTop' : $target.offset().top
                          // ...
                        

                        Das war die Stelle, an der ich dir empfohlen hatte, die Variablenzuweisung zu löschen und statt dessen den Funktionsaufruf direkt bei der Zuweisung zu notieren, da du hier nicht nur eine globale Variable produziert hast, sondern darüber hinaus an diesem Punkt eigentlich überhaupt keine Variablendefinition notwendig war. Denn du verwendest den entsprechenden Rückgabewert von $(target) ja ohnehin nur einmal, nämlich bei eben jener Zuweisung ein paar Zeilen weiter.

                        Nun hattest du zwar die Zeile $target = $(target); wie angeraten gelöscht, aber eben vergessen, bei der Wertzuweisung weiter unten $target durch $(target) zu ersetzen, mit der Folge, dass dir dein Script beim Klick auf einen Link mit einen Reference Error um die Ohren geflogen ist, da nach der Löschung natürlich keine Variable mit dem Bezeichner $target mehr vorhanden war.

                        Du möchtest nun vielleicht etwas genauer wissen, warum ich dir das empfohlen habe?

                        Ok. :-)

                        Ich nehme an, du hast sicherlich verstanden, dass es nicht besonders sinnvoll ist, einen Wert extra in einer Variablen zu hinterlegen, wenn man ihn ohnehin nur an einer einzigen Stelle benötigt, aber zur Verdeutlichung vielleicht nochmal ein kleines Beispiel:

                        var $target = $(target);
                        var offset = $target.offset();
                        var top = offset.top;
                        // ...
                        'scrollTop' : top
                        

                        Theoretisch hättest du das ganze auch so notieren können, also zunächst einmal den Rückgabewert von $(target) in der Variable mit dem Bezeichner $target speichern, dann auf diesem Objekt die Methode offset() aufrufen und deren Rückgabewert in einer Variable mit dem Bezeichner offset hinterlegen, um dann schließlich von diesem Objekt die Eigenschaft top auszulesen, deren Wert dann wiederum einer dritten Variablen zugewiesen wird, also top.

                        Ziemlich umständlich oder?

                        'scrollTop' : $(target).offset().top
                        

                        …ist da doch offensichtlich die deutlich elegantere Schreibweise, würde ich meinen. ;-)

                        Naja, und dann ist da natürlich noch die Sache mit der globalen Variable.

                        Zur Erinnerung, du hattest geschrieben:

                        $target = $(target);
                        

                        Du hast hier also eine Variable erzeugt, ohne das Keyword var zu verwenden, sondern einfach nur, indem du einen Bezeichner, also einen Namen notiert und dann einen Wert zugewiesen hast. Und das ist schlecht. Denn auf diese Weise wird die Variable auch außerhalb deiner Funktion, also überall in deinem Script „sichtbar“ und kann entsprechend überschrieben werden beziehungsweise eine andere globale Variable mit demselben Bezeichner überschreiben!


                        Also das war jetzt eine Menge Information, aber keine Sorge, wenn du nicht alles direkt verstanden hast! Jedenfalls, wenn du JavaScript lernen willst, würde ich empfehlen, einfach mal ins SELFHTML-Wiki zu schauen. :-)

                        Viele Grüße,

                        Orlok

                        1. Hallo, das waren wirklich ganz viele Informationen. Ich bedanke mich für deine Mühe, dass du alles so fein beschrieben hast. Danke :)

                          grüße, mely

                        2. Also das war jetzt eine Menge Information, aber keine Sorge, wenn du nicht alles direkt verstanden hast! Jedenfalls, wenn du JavaScript lernen willst, würde ich empfehlen, einfach mal ins SELFHTML-Wiki zu schauen. :-)

                          Viele Grüße,

                          Orlok

                          Ich kann zwar noch keine Beiträge bewerten, aber wenn ichs könnte, hätte ich hier ein + gegeben :D

                          1. Hallo,

                            Ich kann zwar noch keine Beiträge bewerten

                            Der Zustand ändert sich in Kürze.

                            Gruß
                            Kalk