Javascript fehler
mely
- javascript
- jquery
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
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
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
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
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, undin der Funktion
onScroll
die Anweisungelse { 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
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, undin der Funktion
onScroll
die Anweisungelse { 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
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
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 FunktiononScroll
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 deinemclick
-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 deinemscroll
-Handler liegen, der jedesmal (else
), wenn dieif
-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ürDOMContentLoaded
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
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
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 FunktiononScroll
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()
undposition()
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
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
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
dieif
-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 vononScroll
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
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
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
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
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
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
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
Hallo,
Ich kann zwar noch keine Beiträge bewerten
Der Zustand ändert sich in Kürze.
Gruß
Kalk