Nie obkminiasz działania setTimeout. Czyżbyś wcześniej kodował w innym języku niż JS? Twój kod jest dość zaawansowany jeśli chodzi o funkcjonalność. Algorytmy są stosunkowo skomplikowane. Musisz więc chyba umieć programować, choćby na Javie (chyba że kod robiłeś metoda kopiuj/wklej bez zrozumienia). Nie wykorzystujesz jednak nawet połowy możliwości, jakie daje JavaScript. Wbrew pozorom JavaScript to nie taki zwykły język. W nim programowanie funkcyjne ma bardzo duże znaczenie. I stwarza olbrzymie możliwości, praktycznie niedostępne w Javie, czy C++ (choć Java zapewnia odrobinę jako-takiej funkcyjności za pomocą anonimowych interfejsów).
Sam pomysł z rozbiciem funkcji na czekaj() i gotowe() jest fajny. Ale właśnie z powodu nie zrozumienia działania setTimeout i programowania funkcyjnego to Ci nie działa.
W wywołaniu setTimeout(f, n) f powinno być funkcją, która zostanie wywołana za około n milisekund. To jedyne co robi setTimeout. Samo wywołanie setTimeout(f, n) nie wykonuje się tych n milisekund, to nie działa tak jak delay. To tylko dopisuje funkcję f do jakby JavaScriptowego harmonogramu z czasem wykonania "n milisekund w przyszłości". I kod leci dalej. Czyli jak masz:
a();
setTimeout(f, 100);
b();
To kod wykonuje się tak:
-Najpierw a().
-Potem setTimeout notuje silnikowi przeglądarki, że za 100 ms ma wykonać f.
-Potem (natychmiast!) wykonuje się b()
(... mija ok. 100 ms)
Silnik JavaScript wykonuje zapisaną wcześniej w harmonogramie funkcję f.
Ty popełniłeś jeszcze jeden błąd. Zamiast przekazać do setTimeout funkcję grayscale, przekazałeś wynik działania funkcji grayscale. Niepotrzebnie wstawiłeś nawiasy. Zrobiłeś jakby coś takiego:
setTimeout(f(), 10);
A powinieneś:
setTimeout(f, 10);
W sumie tak naprawdę do setTimeout chcesz przekazać jako parametr f funkcję, która a) wywoła grayscale() i b) wywoła gotowe(). Mógłbyś stworzyć sobie funkcję np. o nazwie fff, która to zrobi, a potem użyć jej tylko raz przekazując ją do setTimeout, o tak:
function fff() {
grayscale();
gotowe();
}
setTimeout(fff, 10);
Ale po co zaśmiecać przestrzeń nazw, skoro JavaScript jest potężnym językiem funkcyjnym i pozwala na łatwe tworzenie funkcji anonimowych? (funkcji bez nazwy, których możemy użyć tylko raz) Można to zrobić tak:
setTimeout(function() {
grayscale();
gotowe();
}, 10);
Czyli w sumie:
<button onclick='czekaj(); setTimeout(function() { grayscale(); gotowe(); } ,10);' class='full' >odc. szarości</button>
Co do formatowania kodu to to temat rzeka. Dotyczy to każdego języka, nie tylko JS. Choć w JavaScripcie jest parę kruczków, które nie są ważne w innych językach. Np. w JS nie powinno się umieszczać znaków { w nowej linii, o tak:
if (a === b)
{
}
else
{
}
Zamiast tego powinno się zrobić tak:
if (a === b) {
} else {
}
W innych językach jest pod tym względem w dowolność. Tymczasem na skutek niefortunnych założeń w JavaScripcie, gdy zrobisz coś takiego (w funkcji zwracasz jakiś obiekt):
return
{
str: 'abc',
num: 123
}
To zostanie to zamienione na (zauważ średnik za return):
return;
{
str: 'abc',
num: 123
};
Ten dodatkowy średnik oczywiście ma katastrofalne skutki -- funkcja nie zwraca nic (undefined). Dlatego nie należy pisać { w nowej linii. Średnik nie będzie dodany, gdy napiszesz to w ten sposób:
return {
str: 'abc',
num: 123
};
Podstawą formatowania są oczywiście wcięcia. Tutaj Twój kod, który na szybko sformatowałem:
function grayscale() {
var stat = document.getElementById('statusTxt'),
imag = document.getElementById('statusImg');
stat.innerHTML = "Czekaj...";
imag.src = "obrazy/stat_wait.gif";
setTimeout(function() {
var mycan = document.getElementById('myCanvas'),
ctx = mycan.getContext('2d'),
imgdata = ctx.getImageData(0, 0, mycan.width, mycan.height),
pix = imgdata.data,
s;
for (var i = 0; i < pix.length; i+=4) {
s = (pix[i] + pix [i + 1] + pix[i + 2]) / 3;
pix[i] = s;
pix[i + 1] = s;
pix[i + 2] = s;
}
ctx.putImageData(imgdata, 0, 0);
stat.innerHTML = "Gotowe.";
imag.src = "obrazy/stat_ok.gif";
}, 10);
}
Już wygląda to inaczej. Ja osobiście korzystam z nieco innego formatowania, niż to powyżej. Trochę brzydszego, ale jeszcze bardziej nastawionego na to, by każda literówka była od razu widoczna lub powodowała błąd składni (który łatwo wykryć).