[js] problem z metodami onmousemove i out

0

Witam, no więc ostatnio bswierczynski pomogl mi z podswietlaniem tabeli. Chcialem isc tym samym krokiem i zrobic sobie chmurki wyswietlajace tekst alternatywny akapitu, ale już nie działa. I nie wiem gdzie jest błąd ;/

function chmurki(){
	var pomoc = ['Al','CZ','ESz','EL','KL','AF','WK','IM','PP'];  // nazwy akapitow
	for (var i=0;i<9;i++){
		var akapity = document.getElementByName(pomoc[i]);
		
		for (var j=0;j<akapity.length;j++){
			var akapit = akapity[j];
			akapit.onmousemove = function(){
				pokaz(evt,this);
			}
			akapit.onmouseout = function(){
				ukryj();
			}
		} 
	}
	
	function pokaz(evt,ak){                         // wyswietlanie chmurek
		var pomoc = ak.getAttribute('alt');
		document.getElementById('pomoc').innerHTML = pomoc;
		document.getElementById('pomoc').style.visibility = 'visible';
		var x = evt.clientX;
		var y = evt.clientY;
		przekaz(x,y);
	}
 
	function przekaz(x,y){
		document.getElementById('pomoc').style.marginLeft = x+10+'px';
		document.getElementById('pomoc').style.marginTop = y+5+'px';
	}	
	function ukryj(){
			document.getElementById('pomoc').style.visibility = 'hidden';
	}
}
chmurki();

a tu html:

<p class="dane" name="RO" alt="Radiootwarzacz">Esz</p>
<p class="dane" name="ESz" alt="Elektryczne szyby">EL</p>
<p class="dane" name="IM" alt="Immobiliser">IM</p>
<p class="dane" name="PP" alt="Poduszki powietrzne">PP</p>
<p class="dane" name="AF" alt="Alufelgi">AF</p>
0

ehmm, jakiś czas temu napisałem podobnego posta:

weź sobie komentuj poszczególne fragmenty tego kodu i dojdziesz do miejsca w którym jest błąd.

0

O FireBugu nie słyszeli?
Web Development Evolved.

0

Poważny błąd (nie wiem czy jedyny) jest tutaj, w linijce oznaczonej gwiazdką:

                        akapit.onmousemove = function(){
                                pokaz(evt,this); // *
                        }

Co to jest evt? Zapewne dostajesz błąd "evt is not defined", czy coś takiego. Ten parametr jest Ci jednak potrzebny w funkcji pokaz, ale nie możesz go sobie wziąć z kosmosu.

Okazuje się, że w większości przeglądarek funkcja podstawiona do onmousemove (lub onmouseover, -out itd.) dostaje za darmo pierwszy parametr oznaczający obiekt reprezentujący zdarzenie (np. ruch myszą).

Ty jednak do onmousemove podstawiasz funkcję, która nie interesuje się swoimi parametrami:

akapit.onmousemove = function() { // lista parametrów jest pusta
  pokaz(evt,this);
}

Przeglądarka i tak da funkcji jeden parametr będący obiektem zdarzenia, ale ponieważ zrobiłeś pustą listę argumentów formalnych, nie możesz się dostać do tego zdarzenia przez nazwę.

Dopisz więc jeden argument do listy argumentów tej funkcji, którą podstawiasz do onmousemove. Możesz go nazwać jak chcesz, np. zdarzenie i przekazać go do funkcji pokaz:

akapit.onmousemove = function(zdarzenie) {
  pokaz(zdarzenie, this);
}

Albo możesz nazwać go tak samo jak w funkcji pokaz, czyli evt:

akapit.onmousemove = function(evt) {
  pokaz(evt, this);
}

Chcę po prostu zaznaczyć, że evt to nie jest żadna specjalna nazwa, dlatego na początku sugerowałem nazwać parametr "zdarzenie".

Jeszcze jeden szkopuł: IE nie przekazuje tego parametru. W IE do bieżącego zdarzenia możesz się dostać używając globalnego obiektu window.event (lub po prostu event). Tutaj nazwa ma już znaczenie.

Jak zadowolić zarówno IE, jak i inne przeglądarki? Zanim przekażesz evt do funkcji pokaz, sprawdź czy evt ma wartość prawdziwą. Jeśli będzie obiektem zdarzenia, to będzie miało taką wartość (tak będzie w Firefoksie, Operze, Safari itd.). Jeśli nIE, to znaczy, że jesteśmy w IE, więc musimy podstawić wartość window.event. W sumie:

akapit.onmousemove = function(evt) {
  if (!evt) {
    evt = window.event;
  }
  pokaz(evt, this);
}

Ze względu na fajne własności operatora || możesz to wszystko zapisać tak króciutko (efekt będzie taki sam, jak powyżej):

akapit.onmousemove = function(evt) {
  pokaz(evt || window.event, this);
}

Operator || działa w JavaScripcie tak, że jeśli napiszesz:

A || B

...to jeśli A jest prawdziwe (jest obiektem, nie-pustym stringiem, liczbą różną od zera itd.), to zwracane jest A. W przeciwnym wypadku zwracane jest B. Czyli np. mając takie coś:

function(evt) {
var zdarzenie = evt || window.event; // *
pokaz(zdarzenie);
}

W linijce oznaczonej * prosimy, by do zmiennej zdarzenie podstawić:
a) wartość evt, jeśli wartość ta jest prawdziwa (czyli jeśli evt zostało przekazane funkcji)
b) wartość window.event w przeciwnym wypadku

Wyniku działania operatora || nie trzeba podstawiać do zmiennej, można od razu przekazać do funkcji pokaz, stąd skrócony zapis:

function(evt) {
pokaz(evt || window.event);
}

Nie mam pojęcia, czy to zadziała bo nie wiem, czy to był jedyny błąd. W razie czego nie płacz ;), tylko odpal konsolę błędów i zobacz komunikaty o błędach JavaScript. W Firefoksie Narzędzia->Konsola błędów, inne przeglądarki też to mają. Najpierw wyczyść konsolę, bo zapewne będzie zapełniona błędami pochodzącymi z różnych stron, które przeglądałeś. Po wyczyszczeniu odśwież swoją stronę -- jeśli wyświetli się jakiś błąd, to przeczytaj komunikat i zrób co trzeba.

0
twoj_mistrz_zxc napisał(a)

var akapity = document.getElementByName(pomoc[i]);

chyba getElementsByName

0

Rozumiem już co robiłem źle, poprawiłem się i potem działało ale tylko w FF. Szukałem na necie i znalazłem że funkcja getElelementsByName w IE i Operze pobiera elementy do kolejki ale tylko wtedy gdy mają one takie samo ID. Inaczej po prostu ich nie widzi. Nadałem elementom te same ID i faktycznie działa znakomicie :) Kolejny raz dzięki za pomoc ;)

P.S. A swoją drogą to nie widziałem że istnieje takie coś jak konsola błędów która wyrzuca wszystkie błędy, bardzo przydatna rzecz.

Pozdrawiam

0

@twoj_mistrz_zxc:
Ja prawie w ogóle nie używam getElementsByName -- z tą funkcją bywają problemy, a poza tym zaleca się korzystanie nie z atrybutu name, tylko id. Pamiętam więc, że id musi być unikalne i korzystam najwyżej z getElementById. Ewentualnie z getElementsByTagName, a potem sprawdzam, czy element ma daną klasę (atrybut className). Tobie również polecam unikać name (a więc funkcji getElementsByName) i używać np. id, klas itp.

Co do konsoli błędów to od teraz Twoje debugowanie będzie wyglądało zupełnie inaczej. Trudno mi uwierzyć ile czasu straciłeś szukając błędu na ślepo -- masakra. Tym bardziej że błędy składni powodują, że skrypt się w ogóle nie wykonuje. Mogłeś jedynie szukać błędów "po staremu", gdy przeglądarki same nie potrafiły ich wskazać. Lata temu robiło się tak, że komentowałeś pół kodu i patrzyłeś, czy błąd składni nadal występuje, tj. czy skrypt się w ogóle odpala. Jeśli się odpalał, to błąd był gdzieś w zakomentowanym obszarze. Dzieliłeś więc komentarz na pół i ponownie sprawdzałeś, czy kod działa, czy nie... itd. itp., aż do namierzenia linijki z błędem. Masakra!

A już od ładnych paru lat przeglądarki potrafi wskazać linijkę, w której jest błąd.

Dodam, że inne przeglądarki też mają podobne konsole. Więc w razie gdy coś tam nie działa, to poszukaj tego przydatnego narzędzia.

Podobnym skokiem jakościowym w debugowaniu jest jeszcze użycie wtyczki typu Firebug. Dalszy krok to opanowanie debuggera w Firebugu (wiele osób korzysta z Firebuga, ale nie z debuggera). Gdzieś pomiędzy może jeszcze być skołowanie IDE (edytora kodu), który w momencie gdy piszesz podświetla Ci błędy składni -- wtedy nie musisz nawet niczego odpalać w przeglądarce, by je zauważyć (inne błędy sprawdzasz już klasycznie). Pomyśl jaka to różnica w porównaniu z prehistoryczną metodą połowienia kodu komentarzami ;). Nie domkniesz klamry -- i po sekundzie edytor podświetla Ci tę linijkę na czerwono.

0

Strasznie mnie to dziwiło dlaczego inne języki od razu pokazują błędy a javascript nie, no ale nie zastanawiałem się jak to jest bo dopiero zaczynam z tym językiem.

Radzisz żeby nie używać getElementsByName, ale jeśli mam sporo akapitów, i procedura wyświetlania chmurek jest taka sama, różnią się tylko treścią. To wydawało mi się że najlepsze rozwiązanie to nadać nazwy odpowiednim i np akapit o name="RO" ma wyświetlać w chmurce 'Radioodtwarzacz', i wyświetlać tym samym sposobem. Czyli w jak mam to zrobić? Bo jeśli by każde miało swoje id to strasznie dużo by tego było ;/

0
twoj_mistrz_zxc napisał(a)

Strasznie mnie to dziwiło dlaczego inne języki od razu pokazują błędy a javascript nie, no ale nie zastanawiałem się jak to jest bo dopiero zaczynam z tym językiem.

Radzisz żeby nie używać getElementsByName, ale jeśli mam sporo akapitów, i procedura wyświetlania chmurek jest taka sama, różnią się tylko treścią. To wydawało mi się że najlepsze rozwiązanie to nadać nazwy odpowiednim i np akapit o name="RO" ma wyświetlać w chmurce 'Radioodtwarzacz', i wyświetlać tym samym sposobem. Czyli w jak mam to zrobić? Bo jeśli by każde miało swoje id to strasznie dużo by tego było ;/

Pokazują, żeby debugować masz konsolę błędów w FF (zakładka Narzędzia), a do deep debuga jest Firebug.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.