I takie podejście jak w mailu mi się podoba. Cieszę się, że masz zamiar to przeanalizować i chcesz sam kod dostosować do siebie. Informacje o tym dzieciaczku wyślę Ci mailem; zobaczysz że sprawa jest niestety poważna i warta zachodu.
Kod wklejam tutaj, żeby było dla potomności. Dla jasności to cały przykładowy plik HTML5 ze wstawionymi czterema licznikami (naturalnie funkcja działa identycznie w HTML-u 4 i XHTML-u).
Funkcja countdown sprawia, że w danym elemencie na stronie (przekazanym jako parametr displayElement) wyświetlany jest zegar odliczający godziny, minuty i sekundy do daty docelowej (parametr targetDate). Jeśli chcesz, to możesz przekazać funkcji trzeci parametr (onCountdownFinish) -- może to być funkcja, która zostanie wywołana gdy zegar osiągnie 0. Zegar wyświetlany jest w formacie HHSS.
Możesz wywołać funkcję countdown ile tylko chcesz razy, byleś tylko podał jej różne elementy, w których ma się wyświetlać zegar. W poniższym przykładzie są cztery zegary.
<!DOCTYPE html>
<html>
<head lang="pl">
<meta charset="utf-8">
<title>Jak zrobic odliczanie czasu w JS i trigger ? (4 programmers.net)</title>
<style>
</style>
</head>
<body>
<h1>Odliczanie czasu</h1>
<p>Licznik pierwszy: <strong id="counter1"></strong></p>
<p>Licznik drugi: <strong id="counter2"></strong></p>
<p>Licznik trzeci: <strong id="counter3"></strong></p>
<p>Licznik czwarty – Odliczanie do alerta: <strong id="counter_alert"></strong></p>
<script>
/**
* Wyświetla zegar odliczający godziny, minuty i sekundy od daty (chwili)
* bieżącej do daty docelowej.
*
* Po osiągnięciu daty docelowej zegar pokazuje zero.
*
* @param targetDate {Date} Data docelowa, reprezentująca chwilę czasu "0"
* @param displayElement {HTMLElement} Element, w którym będzie wyświetlane odliczanie
* @param onCountdownFinish {function} (Parametr opcjonalny) Funkcja, która zostanie
* wywołana gdy odliczanie się skończy. Jeśli
* jako data docelowa będzie podana chwila z przeszłości,
* to funkcja ta będzie wywołana od razu.
*
*/
function countdown(targetDate, displayElement, onCountdownFinish /* = null*/) {
if (!(targetDate && displayElement)) {
return;
}
var formatTimeInterval = function(seconds) {
var hrs = Math.floor(seconds / 3600)
var min = Math.floor(seconds / 60) % 60;
var sec = seconds % 60;
return (hrs + ':' + min + ':' + sec).replace(/(^|:)(\d)(?=:|$)/g, '$10$2');
};
var refreshTimer = function() {
var now = new Date();
var diffMilliseconds = targetDate.getTime() - now.getTime();
var diffSeconds = Math.round(diffMilliseconds / 1000);
if (diffSeconds < 0) {
diffSeconds = 0;
}
var countdownHTML = formatTimeInterval(diffSeconds)
if (countdownHTML != displayElement.innerHTML) {
displayElement.innerHTML = countdownHTML;
}
if (diffSeconds === 0) {
clearInterval(intervalId);
if (typeof onCountdownFinish === 'function') {
onCountdownFinish(targetDate);
}
}
};
var intervalId = setInterval(refreshTimer, 250);
refreshTimer();
}
// Właściwa inicjalizacja zegarów:
(function() {
var now = new Date();
// data docelowa: 3 marca 2010, godz. 20:48:10 (miesiące liczymy od zera, a dni od jeden... lol)
countdown(new Date(2010, 2, 3, 20, 48, 10, 0), document.getElementById('counter1'));
// data docelowa: teraz plus 2 h 12 min 41 sek
countdown(new Date(now.getTime() + (2 * 3600 + 12 * 60 + 41) * 1000), document.getElementById('counter2'));
// data docelowa: teraz plus 1 min 3 sek
countdown(new Date(now.getTime() + (1 * 60 + 3) * 1000), document.getElementById('counter3'));
// data docelowa: teraz + 5 sek
countdown(new Date(now.getTime() + 5 * 1000),
document.getElementById('counter_alert'),
function() {
alert('Licznik czwarty: czas minął!');
}
);
})();
// Więcej o tworzeniu dat:
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date
// Zauważ, że można przekazać konstruktorowi Date czas w milisekundach,
// co bardzo łatwo przerobić na unixowy czas podawany w sekundach.
</script>
</body>
</html>
I co, przyda się to na coś? O coś takiego chodziło?
Edit: Co do tego celu charytatywnego to info poszło właśnie w mailu.
Edit2: Tak sobie myślę, że jakby chodziło Ci to trochę "mało płynnie" (tzn. przeskakiwało czasami co dwie sekundy), to możesz zmniejszyć liczbę przy setInterval z 1000 na np. 500 czy nawet 100. Wtedy zegary będą odświeżane nie co mniej więcej sekundę, tylko co mniej więcej 0.5 lub 0.1 sek. Problem leży właśnie w tym "mniej więcej", bo JavaScript nie gwarantuje, że funkcja przekazana setInterval zostanie wywołana dokładnie po tylu i tylu sekundach. Na szczęście skryptowi to nie przeszkadza i zawsze wyświetla dobry wynik, tyle że może to robić mało płynnie. Updejtowałem stosownie sam kod skryptu.
W tym demie może się wydawać, że pierwszy zegar chodzi trochę nierówno z innymi, ale to dlatego, że data podana jest tam inną metodą: nie chwila obecna plus coś, tylko od razu data. I ta "od razu data" ma zero milisekund, a chwila obecna jakieś tam ma. Funkcja mogłaby na początku obcinać milisekundy (co powinno rozwiązać ten problem), ale to by była mała przesada. Problem ten zniknie jeśli wszystkim zegarom podasz czas tą samą metodą, np. wszędzie z now lub wszędzie wprost -- Ty będziesz chciał pewnie wszędzie wprost, bo czas będzie odczytywany z bazy danych. Użyjesz wtedy konstruktora new Date(sekundy_od_1970 * 1000).