Javascript visszaszámláló - Napi sorsoló

Ebben a cikkben bemutatom, hogyan lehet olyan idő visszaszámláló szkriptet írni, ami minden nap egy konkrét időpontig számol vissza, de ez az időpont lehet a másnap reggeli időpont is akár. Ehhez figyelembe kell venni a szerveridőt is, másképp a kliens ( talán hibás ) órájára lenne bízva, hogy mikor van vége a visszaszámlálásnak. Persze a visszaszámlálásnak akkor van értelme, ha a végén valami történik is. Így szerveroldalon PHP-ból gondoskodni kell arról is, hogy például lefusson egy sorsoló program, ami aztán az eredményeket megjeleníti. Ezt vagy Crontab időzítővel, ha a tárhelyen rendelkezésre áll, vagy eltárolva például adatbázisban, hogy aznap lefutott-e már a sorsolás, és ha még nem, de az idő már lejárt, akkor fusson le. És írja ki az eredményt. Persze a következő sorsolásig a visszaszámlálás már elindul. Ennek megvalósítását mindenkinek magára bízom. Én csak a számlálást mutatom be.

Először is kell két div ( vagy bármi más szöveges html elem ) amibe bekerül majd a visszaszámláló, és a lejáratkor megjelenítendő üzenet. Ezeknek id-ket kel adni. Legyenek "timediv" és "msgdiv" a két azonosító

<div id="timediv"></div>
<div id="msgdiv"></div>

Ez után szükség lesz egy php fájlra. Ebben elő kell állítani azt az időt, ameddig a visszaszámlálásnak tartania kell. És ezt a php változót kell átadni majd a javascript-nek.

<?php
$hour = 21; //Lejárat órája
$min = 21; //lejárat perce
$sec = 0;  //lejárat másodperce

$timeDivId = 'timediv'; //A html elem id-je, ahova a visszaszámláló kerül.
$msgDivId = 'msgdiv'; //A html elem id-je, ahova a sorsolás üzenet kerül
$msg = "Sorsolás folyamatban";

$time = time(); //jelenlegi szerveridő
$time24 = mktime(24,0,0); //Aznap éjfél időpontja

$starttime = mktime($hour,$min,$sec); //a lejárat időpontja
//Ha aznap már elmúlt a lejárati idő, akkor tegnaptól kell
//kezdeni a visszaszámlálást
if ($time < $starttime) {
        $starttime-=86400;
}
//Javascriptben az időt nem mp-ben hanem ezred mp-ben kell megadni
$jstime = ($time24  - $time + $starttime)*1000;
header('Content-type: text/javascript');
?>

Itt tehát minden szükséges adatot meg lehet adni. De ezzel még nincs vége a fájlnak. Gyakorlatilag egy javascript fájl lesz php-ben. Ezért is adtam meg php headerben is a típust. Ezt ugyanúgy meg lehet majd hívni a következő módon, mint egy .js kiterjesztésű fájlt:

<script type="text/javascript" src="countDown24.js.php"></script>

De most akkor jöhet is a javascript része. Először egy névtelen függvényre lesz szükség. Nem lenne muszáj névtelen, de így legalább tutira nem lesz felülírva egy szükséges változó, vagy felüldefiniálva egy másik függvény a globális névtérben.

(function (timeDivId, msgDivId,msg,jstime)
{

})(<?php print '"'.$timeDivId.'","'.$msgDivId.'","'. $msg.'",'.$jstime ?>);

Na azért ebben is van php-, mint látszik. A függvény deklarációt zárójelbe tettem, és utána tettem egy () zárójelpárt, amiben php-val irattam ki a paramétereket. Ezzel a deklarációval le is fut a függvény, és nem kellett neki nevet adni. A paraméterek sorban a számlálót tartalmazó div id-je, a lejárat utáni üzenetet tartalmazó div id-je, az üzenet maga és a szerver idő alapján előállított javascript idő. Azaz idő ezredmásodpercekben számítva.

A változók, amire szükség lesz majd a függvényben.

        var timediv = null;
        var msgdiv = null;
        var d = new Date(); //Dátum objektum létrehozása. Az időt később állítjuk be.
        var i=0; //ciklusváltozó
        var dots=''; //sorsolás folyamatjelző pontozás

Ezen kívül még 3 változó lesz, amik gyakorlatilag újabb függvények, de ebben a formában nem kerülnek be a globális térbe. Csak ebben a zárt, névtelen függvényben lesznek elérhetők, mint egy privát metódus.

Az első függvény az end() nevű. Ami akkor fut le, ha éppen lejárt az idő. Ez a lejárat után 1 perc intervallumot jelent majd. Nem mást tesz, mint kiírja a "Sorsolás folyamatban" szöveget a megfelelő div-be, és egy folyamatjelző animációt.

        var end = function ()
        {
                dots='';
                for(i=1; i<=4-(d.getSeconds() % 4);i++) {
                        dots+='.';
                }
                msgdiv.innerHTML = msg + dots;
        }

A következő maga a visszaszámlálás megvalósításának egy lépése. Ezt kell majd ismételni később:

        var countDown = function()
        {
                jstime-=1000;
                d.setTime(jstime);             
                var minute = (d.getMinutes() < 10) ? '0'+d.getMinutes() : d.getMinutes();
                var sec = (d.getSeconds() < 10) ? '0'+d.getSeconds() : d.getSeconds();
                timediv.innerHTML = d.getHours() + " : " + minute + " : " + sec;
                if(d.getHours() == '23' && d.getMinutes() == '59') {
                        end();
                } else {
                        msgdiv.innerHTML = "";
                }
        }

Ez tehát 1 percig a lejárat idejekor megjeleníti a sorsolás szöveget, mert meghívja az end() függvényt. Más esetben pedig üresre állítja az üzenet div-et. Most jöhet tehát a start() függvény, ami ezt a lépést ismételgeti.

        var start = function()
        {
                timediv = document.getElementById(timeDivId);
                msgdiv = document.getElementById(msgDivId);
                //Ha bármelyik div nem létezik, nem fut le a program
                if (!timediv || !msgdiv)
                {
                        return;
                }
                countDown();
                setInterval(countDown,1000);           
        }

A setInterval() függvény fogja másodpercenként ismételgetni a countDown függvényt. És persze előtte lekérdezi a timediv és msdiv változókba a megfelelő div-eket ( vagy más html elemeket ). Mivel az ismételgető függvény előbb késleltet, aztán futtat, ezért előbb meg kell hívni külön a countDown() függvényt. Így a start meghívásakor azonnal látszik az eredmény. Ez persze így mind szép, de mégis hol lesz ez meghívva? Külön nincs szükség a meghívására, mert most megírjuk azt a pár sort, ami akár Firefox-ban, akár Internet Explorer-ben hozzáadja a window objektum onload eseményéhez a start függvényt. Nem pedig csak szimplán felülírja. Mert esetleg lehet, hogy már valami más script is hozzáadta magát az onload-hoz. És azt nem szeretnénk kilőni.

        if (window.attachEvent) {
                window.attachEvent("onload",start);
        } else {
                window.addEventListener("load",start,false);
        }

Mivel a névtelen függvény azonnal lefut, így ez a fenti kódsor is egyből le fog futni. Viszont a start függvény csak akkor, amikor már a weboldal betöltött. És az pedig csak akkor indítja a visszaszámlálást, ha a szükséges div-ek léteznek. A teljes countDown24.js.php tartalma a következő:

<?php
$hour = 21; //Lejárat órája
$min = 21; //lejárat perce
$sec = 0;  //lejárat másodperce

$timeDivId = 'timediv'; //A html elem id-je, ahova a visszaszámláló kerül.
$msgDivId = 'msgdiv'; //A html elem id-je, ahova a sorsolás üzenet kerül
$msg = "Sorsolás folyamatban";

$time = time(); //jelenlegi szerveridő
$time24 = mktime(24,0,0); //Aznap éjfél időpontja

$starttime = mktime($hour,$min,$sec); //a lejárat időpontja
//Ha aznap már elmúlt a lejárati idő, akkor tegnaptól kell
//kezdeni a visszaszámlálást
if ($time < $starttime) {
        $starttime-=86400;
}
//Javascriptben az időt nem mp-ben hanem ezred mp-ben kell megadni
$jstime = ($time24  - $time + $starttime)*1000;
header('Content-type: text/javascript');
?>

(function (timeDivId, msgDivId,msg,jstime)
{
        var timediv = null;
        var msgdiv = null;
        var d = new Date();
        var i=0;
        var dots='';
               
        var end = function ()
        {
                dots='';
                for(i=1; i<=4-(d.getSeconds() % 4);i++) {
                        dots+='.';
                }
                msgdiv.innerHTML = msg + dots;
        }

        var countDown = function()
        {
                jstime-=1000;
                d.setTime(jstime);             
                var minute = (d.getMinutes() < 10) ? '0'+d.getMinutes() : d.getMinutes();
                var sec = (d.getSeconds() < 10) ? '0'+d.getSeconds() : d.getSeconds();
                timediv.innerHTML = d.getHours() + " : " + minute + " : " + sec;
                if(d.getHours() == '23' && d.getMinutes() == '59') {
                        end();
                } else {
                        msgdiv.innerHTML = "";
                }
        }
       
        var start = function()
        {
                timediv = document.getElementById(timeDivId);
                msgdiv = document.getElementById(msgDivId);
               
                if (!timediv || !msgdiv)
                {
                        return;
                }
                countDown();
                setInterval(countDown,1000);           
        }
       
        if (window.attachEvent) {
                window.attachEvent("onload",start);
        } else {
                window.addEventListener("load",start,false);
        }
       
})(<?php print '"'.$timeDivId.'","'.$msgDivId.'","'. $msg.'",'.$jstime ?>)

A html pedig például:

<html>
<head>
  <title>Visszaszámláló</title>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="countDown24.js.php"></script>
</head>
<body>
<div id="timediv"></div>
<div id="msgdiv"></div>
</body>
</html>

Demo: Megtekintés

Kategóriák: 
Megosztás/Mentés