[JS] this.src

0

Witam,
napisałem funkcję, która pokazuje i ukrywa DIV-a po kliknięciu na obrazek.
Działa bez zarzutu. Teraz próbuję dodać do niej instrukcje, która zmieni również sam obrazek,
a po ponownym schowaniu DIV'a zmieni na poprzedni itd.
Obecnie wygląda to tak:

function show(id)
{
	
	var status=document.getElementById(id).style.display;
	var sciezka='img/' + id;
	
		if (status == "block")
		{
			
			sciezka=sciezka + '.jpg';
			alert(sciezka);
			this.src=sciezka;
			
			document.getElementById(id).style.display = "none";
			
		} else {
			
			sciezka=sciezka + '_click.jpg';
			alert(sciezka);
			this.src=sciezka;
			
			document.getElementById(id).style.display = "block";
			
		}

}


EDIT::
<img src="img/gdansk.jpg" onClick="javascript:show('gdansk');">


Alerty dodałem by widzieć, czy ścieżka do pliku jest poprawna.
Próbowałem również z setAttribute, ale nic z tego nie wychodziło.
Mógłby ktoś mi pomóc? Co robię nie tak, że obrazek się nie zmienia?
Z góry dziękuję, paawian.

0

Nie będę pisał szerzej o fakcie, że we wklejonym przez Ciebie kodzie brakuje drugiej klamry za else (zamykającej blok funkcji) i nie ma w HTML-u elementu #gdansk, bo rozumiem, że w Twojej wersji to jest OK i problemy te pojawiły się przy przeklejaniu kodu.

To robisz źle, że this wewnątrz funkcji nie wskazuje Ci na obrazek. Gdybyś dołączał funkcję obsługi zdarzenia w inny sposób, niż (przestarzały) atrybut onClick umieszczony w kodzie, to miałbyś z tym mniej problemów. A tak... w onClick masz po prostu zwykły kod JavaScript. Kod ten tworzy jakby blok, w którym this związane jest rzeczywiście z elementem, który wyzwolił zdarzenie -- czyli z obrazkiem.

Niestety, z powodu błędu w specyfikacji JavaScriptu to "this" nie jest zanoszone do wnętrza funkcji wywoływanej w tym bloku (to, na co wskazuje this, nazywamy "kontekstem funkcji", lub po prostu "kontekstem"). Funkcja nie dziedziczy automatycznie kontekstu z bloku kodu, w którym została wywołana. Czyli wewnątrz onclick this wskazuje na obrazek, ale wewnątrz odpalanej tam funkcji już nie. Tam wskazuje tak naprawdę na obiekt globalny, czyli window. Pisząc "this.src = 'abc'" piszesz więc jakby "window.src = 'abc'". Nie to, co chciałeś.

Problem z kontekstem możesz jednak rozwiązać ręcznie. Zauważ, że wewnątrz onclick -- tam, gdzie kontekst jest jeszcze poprawny -- przekazujesz funkcji show parametr. Przekazujesz wartość 'gdansk', a funkcja odbiera go jako argument formalny o nazwie id. W ten sam sposób możesz przekazać kontekst.

W definicji funkcji dodaj drugi argument formalny. Nazwij go np. source, czyli źródło [źródło zdarzenia; element, który wyzwolił zdarzenie]. Za chwilę zadbamy, by argument ten otrzymał referencję do naszego obrazka, więc zamień wszystkie this wewnątrz funkcji na source. Jak już załatwiłeś deklarację funkcji, to teraz wystarczy w onClick przekazać jej ten drugi argument. Przekaż jej oczywiście po prostu this (bez żadnych apostrofów itp.). this to referencja do obrazka, którą funkcja zna wewnątrz siebie pod nazwą source.

Jest jeszcze drugie rozwiązanie. Krótsze i wymagające mniej zmian, ale ono jest dla zaawansowanych. Ponieważ Ty jeszcze nie formatujesz nawet poprawnie kodu i nie robisz ładnych wcięć, musisz jeszcze trochę dorosnąć, zanim będziesz mógł tego używać :P (tak, to jest wjazd na ambicje! formatuj kod! każdy kod chce być piękny -- Twój też!).

Kontekstem w JavaScripcie można sterować. By to jednak skumać, powinieneś już znać się na dziedziczeniu prototypowym i w ogóle obiektowym modelu zastosowanym w JavaScripcie, także przyjdzie na to czas. Nadmienię tylko, że zamiast wywołania w onClick show('gdansk'), trzeba by użyć show.call(this, 'gdansk'). Wtedy kontekst wewnątrz show byłby ustawiony poprawnie i wszystko by Ci śmigało. Na razie masz jednak do dyspozycji prostsze rozwiązania (prostsze do zrozumienia, bo głupio używać kodu, którego się nie rozumie!).

I co, pomogło? Sytuacja opanowana?

PS. Tak w ogóle to problem kontekstu jest znany i nie lubiany przez rzesze koderów JS na świecie. Mnóstwo szczególnie profesjonalnych programistów ma z tym kłopoty. Także każda chwila poświęcona na zrozumienie tego problemu nie jest chwilą straconą.

0

Co chcesz od mojego onclicka?!
Daj mu spokój ;p

Może i pomogło, może nie pomogło, zobaczymy.

Trzeci rok programuję w różnych językach i wcięcia tu mi nie były potrzebne to ich nie zrobiłem.

A element gdansk to DIV, który ma się pokazywać, a którego tu nie umieściłem bo z nim nie ma problemów.

EDIT:
Po drugim argumencie działa. Ale zaintrygowałeś mnie zmianą sposobu i zamierzam to zastosować.
Tak czy inaczej, dzięki.

Jeśliby to kogoś interesowało, to tak działa:

function show(id,source)
{
       
        var status=document.getElementById(id).style.display;
        var sciezka='img/' + id;
       
                if (status == "block")
                {
                       
                        sciezka=sciezka + '.jpg';
                        source.src=sciezka;
                       
                        document.getElementById(id).style.display = "none";
                       
                } else {
                       
                        sciezka=sciezka + '_click.jpg';
                        source.src=sciezka;
                       
                        document.getElementById(id).style.display = "block";
                       
                }

}


EDIT::
<img src="img/gdansk.jpg" onClick="javascript:show('gdansk',this);">
0
paawian napisał(a)

Co chcesz od mojego onclicka?!

Skoro już pytasz :D, a programujesz trzeci rok, to mogę odpowiedzieć...
-Narusza zasadę rozdzielenia warstw (prezentacja, struktura, zachowanie), będąc zachowaniem umieszczonym w strukturze.
-Tak naprawdę jest tym samym co wywołanie eval. Jest takie stare, chińskie porzekadło o JavaScripcie: "eval is evil". Utrudnia debugowanie. Spowalnia program. Ukrywa błędy składni (składnia wewnątrz eval nie jest przetwarzana zaraz po wczytaniu skryptu).
-To "javascript:" na początku jest tak czy siak zbędne.

Dalsze czytanie: o zastosowanym przez Ciebie sposobie (również czemu jest be), o prostej alternatywie, o bardziej skomplikowanych, ale potężniejszych (profesjonalnych!) sposobach

paawian napisał(a)

Trzeci rok programuję w różnych językach i wcięcia tu mi nie były potrzebne to ich nie zrobiłem.

Tak nie były potrzebne, że nie zauważyłeś braku klamry :). Poza tym wcięcia i w 15 linijkach poprawiają czytelność!

paawian napisał(a)

Tak czy inaczej, dzięki.

Proszę bardzo. Btw., polecam książkę "JavaScript - mocne strony", której autorem jest Douglas Crockford. Bardzo zwięzła, ale umiejętnościom programowania w JavaScripcie daje potężnego kopa w tyłek.

edit: O, więc jednak masz ukryte umiejętności formatowania kodu! ;)

Jeszcze jedna podpowiedź, już nie o JavaScripcie, tylko o forum (niestety chyba nigdzie nie jest to opisane, więc każdy musi się dowiedzieć na własną rękę). Otóż w tagu otwierającym < code > możesz po znaku równości (żadnych spacji!) podać nazwę języka programowania. Wtedy powinno zadziałać kolorowanie składni. Wspieranych jest kilka języków, JavaScript też (< code = javascript>, tylko że bez spacji).

edit2: Jeśli zainteresowany jesteś kontekstem, to wyszperałem Ci poświęcony tylko temu artykuł na A List Apart. Wg mnie może się wydawać trochę zawiły. Wymaga np. jakiejś wiedzy o programowaniu funkcyjnym (kolejna ekstremalnie ważna rzecz w JS). Może jednak dasz radę to ogarnąć. Ja bym raczej nie dał bez solidnych podstaw z programowania funkcyjnego, prototypowania i cholera wie czego jeszcze.

0

Staram się skorzystać z prostej alternatywy, o której mówiłeś.

<script type="text/javascript" language="javascript">

oferta.onmouseover=zmien;

function zmien()
{
	
          this.src='img/oferta_over.jpg';
	
}

</script>

<img class="menu" id="oferta" name="oferta" src="img/oferta.jpg" />

Nie działa, nie mam pojęcia dlaczego. Jeszcze raz proszę o pomoc, próbowałem już wielu kombinacji składni.

0
  1. W funkcji zmien(), this oznacza tak naprawdę obiekt window, a nie element
  2. Nie ma takiej zmiennej, jak oferta

Poszukaj o podpinaniu zdarzeń, events, itd. :)

0
kubARek napisał(a)
  1. W funkcji zmien(), this oznacza tak naprawdę obiekt window, a nie element
  2. Nie ma takiej zmiennej, jak oferta

Poszukaj o podpinaniu zdarzeń, events, itd. :)
\

no tak faktycznie, już mi o tym bswierczynski napisal -.-
glupek ze mnie, nvm, dziekuje

1 użytkowników online, w tym zalogowanych: 0, gości: 1