Jak zrobic odliczanie czasu w JS i trigger ?

0

Witam.
Potrzebuje zrobić odliczanie czasu dla kilku wartości z bazy danych. Nie chodzi o gre jak możnaby się było domyślać. Ale nie przeszkadza to by w grze takie coś było. Chodzi o to, że mam w bazie zapisane dla przykładu 3 rekordy. Każdy rekord ma pole EXPIRED TIME. Jest tam zapisany znacznik czasu UNIX. Pobieram obecny znacznik i dodaje obliczony czas przyszlosciowy w sekundach. Tak jak radziliscie w innym poście. Teraz gdy wchodze na strone i pobieram te 3 rekordy to pobieram znacznik UNIXA i odejmuje obecna wartosc. Jesli jest > 0 znaczy ze powinienem wlaczyc licznik. Chodzi mi o to jak zrobić to odliczanie dla tych 3 rekordow lub wiecej jednoczesnie na stronie. Czy to sie da napsiac w JS ? zeby tworzyl obiekt i wpsial czas oraz wysweitlal go na stronie ? Czy moze ktoś natrafił gdzieś na strone z gotowym skryptem tego typu. Jeśli można to prosze Was o pomoc. Jak to rozwiazać najlepiej ?

Jesli chodzi o triggera (mechanizm wyzwalajcy) to jak zrobic by po odliczeniu wywolac dana funkcje z parametrami ktrore dotycza danego timer. Jesli skonczy sie czas dla rekordu drugiego to zeby zmodyfikowac dane dotyczace wlasnie danego rekordu w bazie.

I dodatkowo co 15 sekund zeby sie strona dosweizala, ale to chyba wiem jak zrobic w JS
poporstu dac odsweizanie strony w ajaxie zeby dzialo sie to w tle.

0

@masterO:
Tak, od tego jest JS. Czy ma być tam taka opcja, żeby np. naraz wyświetlały się na stronie 3 liczniki, dla tych 3 rekordów?

Btw. to nie jest przypadkiem skrypt dla strony typu "aukcje [z podbiciami] za grosz"?

0
bswierczynski napisał(a)

@masterO:
Tak, od tego jest JS. Czy ma być tam taka opcja, żeby np. naraz wyświetlały się na stronie 3 liczniki, dla tych 3 rekordów?

Btw. to nie jest przypadkiem skrypt dla strony typu "aukcje [z podbiciami] za grosz"?

Tak dokladnie ma byc tak ze jesli wysweitle 10 rekorodw na stronie to zeby na tych 10 rekordach odliczal się czas do zakończenia zlecenia. I jesli skonczy sie czas dla danego rekordu to zeby zmienil sie status danego zlecenia. Ale teraz tak. Nie mozna polegac na JS na zmiaie statusu. Wiec zrobilem tak, że jeżeli na dane zlecenie nie przyjdzie jakas akcja zmieniajaca status ze skryptu PHP To jesli ma wybrac ponownie rekordy do wysweitlania a czas bedzie ujemny to tego rekordu nie wysweitli a skrypt zmieni mu status na EXPIRED. W każdym razie potrzebuje tak:

BTW: jest to podobny skrypt jak te z groszami ale tu ma po wylicczeniu nie podbijac groszy tylko zamknac zlecenie

  1. Skrypt w JS ktory odlicza czas w tyl
  2. po skonczeniu skryptu zeby wywolywal funkcje odswiezania strony w tle (AJAX)
  3. Funkcje w JS ktora odswiezac bedzie strone w tle (AJAX) co 15 sekund

Znalazlem taki skrypt na odliczanie czasu:

function liczCzas()
{
  now = new Date();
  rok = now.getFullYear();
  miesiac = now.getMonth();
  dzien = now.getDate();
  to = new Date(rok,miesiac,dzien,12,0,0);
  ile = to.getTime() - now.getTime();
  godzin = Math.floor(ile / (1000 * 60 * 60));
  minut = Math.floor( ile / (1000 * 60)-godzin*60);
  sekund = Math.floor(ile / 1000 - godzin*60*60 - minut*60);
  if (godzin < 0)
  {
    to = new Date(rok,miesiac,dzien+1,12,0,0);
    ile = to.getTime() - now.getTime();
    godzin = Math.floor(ile / (1000 * 60 * 60));
    minut = Math.floor(ile / (1000 * 60)-godzin*60);
   sekund = Math.floor(ile / 1000 - godzin*60*60 - minut*60);
  }
  document.getElementById("time").innerHTML = "Pozostalo: "+godzin+" 
... godzin, "+minut+" minut, "+sekund+" sekund";
  }
var animeInt;
clearInterval(animeInt);
animeInt = setInterval("liczCzas()", 1000);

W body teraz trzeba jeszcze dodać
<div id="time"></div>

i w body onload="liczCzas();"

W skrypcie zauwazylem takie zmienne:
now = new Date(); czyli pobiera aktualna date
to = new Date(rok,miesiac,dzien,12,0,0); Data docelowa
ile = to.getTime() - now.getTime(); Różnica w czasie miedzy tymi datami

To jak rozumiem zamiast umieszcczac w JS obliczanie zmiennej ILE
to poporstu to ILE przekazuje do funkcji JS i na tej podstawi sobie oblicze ile zostalo.
Tylko jak teraz podlaczyc te funkcje do kilku obiektow zeby liczylo na kazdym obiekcie oddzielnie ?

0

@masterO:
No właśnie, ta funkcja jest bardzo wątpliwej jakości. Nie da się jej "podłączyć", bo została napisana totalnie nieelastycznie. Oprócz tego śmieci zmiennymi globalnymi i wykorzystuje ukryte eval -- i robi te rzeczy zupełnie niepotrzebnie (tj. można najzwyczajniej w świecie zmienić zmienne globalne na lokalne i eval na przekazanie funkcji i niczego innego nie ruszać i będzie działało). A co robi linijka:

clearInterval(animeInt);

to już tylko autorowi zdawało się że wie (bo tak naprawdę nie wiedział; jest ona zupełnie bezsensowna). Nie wspomnę o "świetnym" nazewnictwie zmiennym typu "ile" i pomieszanie polskiego z angielskim (dzien, miesiac, ale "now" i "to").

Nawiasem mówiąc ktoś, kto to napisał nie za bardzo znał język JavaScript i nie był zbyt dobrym programistą. Komuś, kto zna JS wystarczyłoby pewnie z pół godzinki na napisanie odpowiedniej (i dużo lepszej) funkcji. Skoro potrzebujesz tego JS-u, to może zainwestuj i sam się naucz? W necie jest naprawdę pełno śmieci i trudno wierzyć, że kolejny ściągnięty skrypt jest dobrej jakości. Tym bardziej, że -- jak widać -- ciężko zauważyć, że dany skrypt jest lipny, jeśli samemu nie zna się dobrze danego języka.

Nie wolałbyś żeby to się wyświetlało w formacie HHSS, tak w ogóle?

UPDATE:
Jak chcesz to mogę zrobić dobry uczynek i dać Ci tę funkcję, ale w zamian musiałbyś się przynajmniej zastanowić nad tym, żebyś i Ty zrobił dobry uczynek i -- jeśli możesz -- zrobił jakąś dowolną wpłatę (choćby parę złotych) na wskazany przeze mnie cel charytatywny (małe i bardzo chore dziecko). Sprawdzał tego nie będę, ot kwestia honoru i dobrej woli.

Tutaj raczej nie dajemy gotowych rozwiązań, a jak już to w ramach działu Praca, ale ja pracował za parę groszy nie będę. Co innego gdy mogę zachęcić Cię do nauki JS, sprawić, że w necie będzie 1 słaby skrypt mniej i jeszcze Ty (poniekąd dzięki mnie) możesz zrobić dobry, anonimowy uczynek. Hm?

0

Odpisalem na maila jak widze klase takiej funkcji jesli mozesz pomoc to chetnie skorzystam z pomocy. A cel jaknajbardziej jest honorowy wiec bez wzgledu na inne kwestje napisz wiadomosc ze szczegolami wplaty

0

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 &ndash; 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).

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