Hallo,

Ik ben een total noob als het aankomt op javascript. So bare with me please...

Ik ben bezig met een website. Deze website maakt gebruik van een database. In deze database staan entries met geldbedragen. Deze geldbedragen laat ik de database bij elkaar optellen en dat is dus het bedragTotaal (o.i.d.). Het script en de database hiervoor moet ik nog maken.

Op deze website wil ik graag een realtime teller tonen (javascript?) die iedere seconde controleert wat het bedragTotaal is. Wanneer dit omhoog is gegaan dient de teller naar boven te worden bijgesteld. Het liefst zie ik dan de cijfers naar boven 'wegrollen' zoals je bij een gasmeter ook hebt. Dit zal dus een soort transitie of animatie moeten zijn.

Wie kan mij op weg helpen want ik heb gezocht, maar kom geen script tegen waar ik iets mee kan.

EDIT:
Ik heb een script gevonden dat optelt:
http://developer.mindtouch.com/User:Howleyda/Plain_Ticker

Helaas werkt het nog niet. Vreemd, want op de developers page werkt het uitstekend. Maar hoe kan ik er voor zorgen dat het script iedere seconde het bedragTotal controleert en optelt vanaf het huidige bedragTotal naar het nieuwe bedragTotal? En is het dan mogelijk om een soort van transitie toe te voegen? Bijvoorbeeld dat de eerste en laatste cijfers langzamer gaan dan de middelste?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
</head>

<body>

<h1>Jquery Number Ticker - By Damien Howley</h1>
<div class="counter-wrap">
	<div class="counter-number">
		&nbsp;
	</div>
</div>

<div>
<style>
.counter-wrap {
	height:18px;
	overflow:hidden;	
}
.counter-number {
	height:198px;
	width:12px;
	position:relative;
	background-image:url(img/counter_ticker_bg.gif);	
	float:left;
}
</style>
<a href="#" onclick="loadticker(0786554)">load ticker - 786554</a><br/><br/>
<a href="#" onclick="loadticker(01767697234789837)">load ticker - 1767697234789837</a><br/><br/>
<a href="#" onclick="loadticker(01988989)">load ticker - 1988989</a><br/><br/>

</div>

<script src="js/jquery-1.4.4.min.js" type="text/javascript"></script>
<script type="text/javascript">
Deki.$(".counter-number").each( function(i) {
	Deki.$(this).attr('id','num'+i);
});

function loadinput() {
	var newval = Deki.$("#numgo").val();
	loadticker(newval);
}

function loadticker(ticnum) {
	var fticnum = add_commas(ticnum);
	var numheight=18;
	addticker(fticnum);
	if (ticnum && ticnum != 0) {
		
		var s = String(fticnum);
		
		for (i=s.length;i>=0; i--)
		{
			var onum=s.charAt(i);			
			Deki.$("#num"+i).attr('value',onum);
		}
		
		Deki.$(".counter-number").each( function() {
			var nval=Deki.$(this).attr("value");
			if (!isNaN(nval)) {
				var nheight = Number(nval)*numheight*-1;
				Deki.$(this).animate({ top: nheight+'px'}, 1500 );
			} 
			if (nval==','){
				Deki.$(this).animate({ top: '-180px'}, 1500 );
			}
  		});
	}
}

function addticker(newnum) {
	var digitcnt = Deki.$(".counter-number").size();
	var nnum = String(newnum).length;
	var digitdiff = Number(nnum - Number(digitcnt));
	if (digitdiff <0) {
		var ltdig = (Number(nnum)-1);
		Deki.$(".counter-number:gt(" + ltdig + ")").remove();
	}
	
	for(i=1;i<=digitdiff;i++) {
		Deki.$(".counter-wrap").append('<div class="counter-number" id="num' + (Number(digitcnt+i-1)) + '">&nbsp;</div>');
	}
}

function add_commas(nStr) {
	nStr += '';
	x = nStr.split('.');
	x1 = x[0];
	x2 = x.length > 1 ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, '$1' + ',' + '$2');
	}
	return x1 + x2;
}


</script>

</body>
</html>
Aah, stukje bij beetje geef je je requirements prijs.

Om vanuit javascript de oversteek te maken naar de server, waar de databasewaarden bekend zijn, heb je toch die $.ajax nodig. $.ajax roept een van je functies aan als het resultaat terugkomt. Ik zou het server-script zo laten als in mijn eerste voorstel; de huidige waarde ken je immers in de javascript al. Die moet dan wel ergens blijven.

De sequentie van je applicatie wordt dan zo:
[server] componeer pagina
[browser] toon de eerste totaalwaarde in de relevante html-container (div), sla dat op in (bijvoorbeeld) huidigTotaal
1) per timer (doe maar setTimeout) vraag een totaal aan de server
2) is het verkregen antwoord gelijk aan huidigTotaal? ja -> stap 1
3) zet startValue op huidigTotaal, en endValue op het verkregen antwoord. Geef de ticker een stop-handler(*). Start de ticker.
4) (de stop-handler) ga verder bij 1

Hoe doe je dat, stop-handler? Je Timer roept bij elke tik de functie timer_tick aan; daarin zit een test op de eindconditie. Daaronder moet je dus je stap-1-timeout weer instellen.
Bas Cost Budde op 19/12/2010 20:47:31

Aah, stukje bij beetje geef je je requirements prijs.
Sorry, dat is niet bewust. Ik probeer het allemaal zo duidelijk mogelijk uit te leggen, maar ik ben zo'n ontiegelijke noob als het om javascript/ajax gaat. Ik kan in javascript nog geen simpele classe schrijven.

Bas Cost Budde op 19/12/2010 20:47:31

Ik zou het server-script zo laten als in mijn eerste voorstel; de huidige waarde ken je immers in de javascript al.

Voor de zekerheid: Je bedoelt dit script:

<div id="counter"></div>
<script type="text/javascript">
window.setInterval(pollServer, 10000);

function pollServer() {
$.get('bedrag_server.php', function(data) {
  $('#counter').html(data);
});
}
</script>
Dat werkte namelijk goed.

Bas Cost Budde op 19/12/2010 20:47:31

Die moet dan wel ergens blijven.
Kan ik dan binnen de functie een var aanmaken? En hoe gebruik ik die var dan weer?

Bas Cost Budde op 19/12/2010 20:47:31

De sequentie van je applicatie wordt dan zo:
[server] componeer pagina
[browser] toon de eerste totaalwaarde in de relevante html-container (div), sla dat op in (bijvoorbeeld) huidigTotaal
1) per timer (doe maar setTimeout) vraag een totaal aan de server
2) is het verkregen antwoord gelijk aan huidigTotaal? ja -> stap 1
3) zet startValue op huidigTotaal, en endValue op het verkregen antwoord. Geef de ticker een stop-handler(*). Start de ticker.
4) (de stop-handler) ga verder bij 1

Hoe doe je dat, stop-handler? Je Timer roept bij elke tik de functie timer_tick aan; daarin zit een test op de eindconditie. Daaronder moet je dus je stap-1-timeout weer instellen.
Volgens mij sla je hiermee de spijker op zijn kop. Klopt het dat bij deze opzet het script niet opnieuw controleert op een nieuwe waarde zolang de teller nog loopt?

Ik moet dus jouw script en deze teller ineen zien te krijgen en hier en daar tweaken?

Bedankt voor je geduld overigens. Alhoewel ik redelijk kan scripten in php, vind ik dit echt onwijs moeilijk te begrijpen. Heb nog geen flauw idee hoe ik een simpele var kan weergeven. Bedankt alvast.
The Ultimate op 19/12/2010 20:58:45

[quote="Bas Cost Budde op 19/12/2010 20:47:31"]
Aah, stukje bij beetje geef je je requirements prijs.

Sorry, dat is niet bewust. Ik probeer het allemaal zo duidelijk mogelijk uit te leggen, maar ik ben zo'n ontiegelijke noob als het om javascript/ajax gaat. Ik kan in javascript nog geen simpele classe schrijven.
[/quote]
Dat neem ik je niet kwalijk. Je kunt er wel wat aan doen: stel de technische vragen uit, totdat je een gewone-taal-verhaaltje af hebt dat je aan een van je kinderen zou durven uitleggen.

The Ultimate op 19/12/2010 20:58:45

[quote="Bas Cost Budde op 19/12/2010 20:47:31"]
Ik zou het server-script zo laten als in mijn eerste voorstel; de huidige waarde ken je immers in de javascript al.

Voor de zekerheid: Je bedoelt dit script:

<div id="counter"></div>
<script type="text/javascript">
...

Dat werkte namelijk goed.
[/quote]
nee, het server-script is php. Hier zit een stukje dat nog geen goede plek in je kennis heeft, zie ik.

The Ultimate op 19/12/2010 20:58:45

[quote="Bas Cost Budde op 19/12/2010 20:47:31"]
Die moet dan wel ergens blijven.
Kan ik dan binnen de functie een var aanmaken? En hoe gebruik ik die var dan weer?
[/quote]
Niet binnen de functie, want dan heeft hij een te beperkte scope. Op de plek waar je je eerste setTimeout uitvoert, maak je ook de variabele.

The Ultimate op 19/12/2010 20:58:45

[quote="Bas Cost Budde op 19/12/2010 20:47:31"]
De sequentie van je applicatie wordt dan zo:
[server] componeer pagina
[browser] toon de eerste totaalwaarde in de relevante html-container (div), sla dat op in (bijvoorbeeld) huidigTotaal
1) per timer (doe maar setTimeout) vraag een totaal aan de server
2) is het verkregen antwoord gelijk aan huidigTotaal? ja -> stap 1
3) zet startValue op huidigTotaal, en endValue op het verkregen antwoord. Geef de ticker een stop-handler(*). Start de ticker.
4) (de stop-handler) ga verder bij 1

Hoe doe je dat, stop-handler? Je Timer roept bij elke tik de functie timer_tick aan; daarin zit een test op de eindconditie. Daaronder moet je dus je stap-1-timeout weer instellen.

Volgens mij sla je hiermee de spijker op zijn kop. Klopt het dat bij deze opzet het script niet opnieuw controleert op een nieuwe waarde zolang de teller nog loopt?
[/quote]
Zo is het. Maar, mijn eerste voorstel ging uit van een doorlopend vragen aan de server, met setInterval. Je kunt beter setTimeout gebruiken; elke keer als de timeout afgaat, heb je namelijk de keus:
- waarde dezelfde? nieuwe timeout zetten
- waarde veranderd? Timer maken, gasmeter-circus starten

The Ultimate op 19/12/2010 20:58:45

Ik moet dus jouw script en deze teller ineen zien te krijgen en hier en daar tweaken?

Bedankt voor je geduld overigens. Alhoewel ik redelijk kan scripten in php, vind ik dit echt onwijs moeilijk te begrijpen. Heb nog geen flauw idee hoe ik een simpele var kan weergeven. Bedankt alvast.


Ja, dat heb je goed. Toch raad ik je aan om altijd je probleem eerst in mensentaal op te schrijven, en dat verhaal dan vanuit machinaal verwerken proberen te lezen. Bij elke stap vraag je je af: heb ik nu genoeg gegevens om deze opdracht uit te voeren?
Pas wanneer het proces duidelijk is, ga je technische oplossingen zoeken.
Ok, duidelijk verhaal. Ik ga er mee aan de slag en zal in de loop van morgenochtend/middag een reactie plaatsen.

Voor wat betreft dat server-side/client-side stukje: dat had ik verkeerd gelezen. Ik weet gelukkig wel dat php-serverside is en javascript clientside. Het php-script gebruik ik inderdaad zoals jij mij dit gaf.

Vanavond ga ik me inlezen in het setTimeout gedeelte.

Thanks for your support en tot morgen!

[size=xsmall]Toevoeging op 20/12/2010 09:24:34:[/size]

Ok, ik heb aan een script gewerkt. Dit is tot nu toe het resultaat:

<html>
<head>
<script src="js/jquery-1.4.4.min.js" type="text/javascript"></script>
<script type="text/javascript">
var cStart=50;
var t;
var timer_is_on=0;
var cEnd=getEndValue();

function timedCount()
{

	document.getElementById('txt').value=cStart; // Waarde in HTML object plaatsen
	
	cStart=cStart+1; // Wat moet er met de waarde gebeuren
	
	if(cStart<=cEnd) // Stoppen wanneer de Timer op cEnd staat
	{
		// Functie aanroepen (oneindige loop)
		t=setTimeout("timedCount()",500);
	} else 
	{
		// cEnd opnieuw controleren na 10 seconden
		alert('Einde bereikt');
	}
}

function doTimer()
{
	if (!timer_is_on) // Timer staat uit
	{
		timer_is_on=1; // Timer aanzetten
		timedCount(); // Tellen starten
	}
}


function displayStartValue()
{
	$.get('get_amount.php', function(data)	{ $('#startValue').html(data);	} );
}

function getEndValue()
{
	$.get('get_amount.php',
		function(data)
		{
//			document.getElementById("endValue").innerHTML = data;
			endValue = data;
		}
	);
}

</script>
</head>

<body>

<script type="text/javascript">
// Uitvoeren
window.onload=displayStartValue();

</script>

<form>
<input type="button" value="Start count!" onClick="doTimer()">
<input type="text" id="txt">
</form>
<p>Click on the button above. The input field will count forever, starting at 0.</p>

<p>De startwaarde is <span id="startValue"></span></p>
<p>De eindwaarde is <span id="endValue"></span></p>

</body>
</html>
Alleen schijnt var cEnd=getEndValue(); niet te werken. Hoe kan ik gebruik maken van de variabele endValue uit de functie getEndValue()?
Zoals je in displayStartValue doet, gaat de waarde direct naar het scherm, en dat wil je niet he. In getEndValue heb je de variabele cEnd binnen de scope--een geintje van javascript voor je. Doe je dus niet
endValue = data;
maar
cEnd = data;
, dan ben je tot zover gered.

Merk op dat het een asynchrone oproep is. Het is niet de *functie* getEndValue die de waarde teruggeeft. Voor alle duidelijkheid kun je die beter anders noemen (askEndValue ?)
@Bas:
Haha, super. Dat werkt inderdaad.

Ik denk dat ik teveel in php denk door resultaten als het ware te proberen te echoen maar ik begrijp dat je in javaascript dus telkens de var overschrijft?

Ik heb van getEndValue -> checkEndValue gemaakt.

Nu moet ik nog een functie creeeren die - wanneer de teller niet loopt - om de 10 seconden controleert of de cEnd is veranderd door checkEndValue aan te roepen. Waar denk je dat ik deze functie het beste kan plaatsen? In timedCount(), doTimer() of juist helemaal apart?

EDIT:
Het script is inmiddels zover gevorderd. Helaas zie ik de timer nog niet:

<html>
<head>
<script src="js/jquery-1.4.4.min.js" type="text/javascript"></script>
<script type="text/javascript">

var cStart=timerStartValue();
var t;
//var timer_is_on=0;
var cEnd=timerEndValue();

function startCount()
{
	// Beginwaarde en eindwaarde ophalen
	timerStartValue();
	timerEndValue();

	// Timer starten
	timedCount();

	// Na 10 seconden controleren of de cEnd is gewijzigd.
	setTimeout("checkEndValue()",10000);
}

function checkEndValue()
{
	// Oude timerEndValue opslaan
	cEndOld=cEnd;
	
	// Nieuwe timerEndValue opvragen
	timerEndValue();

	// Oude en nieuw timerEndValue met elkaar vergelijken
	if(cEndOld!=cEnd){
		// Teller opnieuw starten
		timedCount();
	} else {
		// Over 10 seconden weer controleren
		setTimeout("checkEndValue()",10000);
	}
}

function timedCount()
{
	document.getElementById('txt').value=cStart; // Waarde in HTML object plaatsen
	
	cStart=cStart+1; // Wat moet er met de waarde gebeuren
	
	if(cStart<=cEnd) // Stoppen wanneer de Timer op cEnd staat
	{
		// Functie aanroepen (oneindige loop)
		t=setTimeout("timedCount()",500);
	}
}

function timerStartValue()
{
	$.get('get_amount.php',
		function(data)
		{
			cStart = data - 10;

			// Beginwaarde tonen
			document.getElementById("startValue").innerHTML = cStart;
		}
	);
}

function timerEndValue()
{
	$.get('get_amount.php',
		function(data)
		{
			cEnd = data;

			// Eindwaarde tonen
			document.getElementById("endValue").innerHTML = data;
		}
	);
}

</script>
</head>

<body>

<script type="text/javascript">
// Uitvoeren
window.onload=startCount();

</script>

<p>De startwaarde is <span id="startValue"></span></p>
<p>De eindwaarde is <span id="endValue"></span></p>
<p>De timer staat nu op: <span id="txt"></span></p>

</body>
</html>

Heeft iemand enig idee waarom de <span id="txt"> de timer niet toont?
Apart.

Je doet er ook goed aan, overigens, de functienamen iets specifieker te maken. Je werkt met twee telcycli: eentje is de wachtlus, die elke 10 seconden een nieuw totaal opvraagt; de andere is de looplus, die het telmechaniek aandrijft.

Breid displayStartValue uit: stop de waarde niet alleen in de html, maar ook in een variabele; en op die plek kun je ook de wacht-teller aanzwengelen (met setTimeout)

De $.get-aanroep naar de server staat nu al twee keer in je code. Je kunt overwegen om die apart te zetten, met een methodenaam als withTotalDo.

Spoiler:

var currentTotal;
var idleTimeout; // om een gezette timeout te clearen als de teller moet oplopen

$(document).ready(function() {
  withTotalDo(showStartValue);
  poll();
});

function poll() {
  idleTimeout = window.setTimeout(keepPolling, 10000);
}

function keepPolling() {
  withTotalDo(rollIfChanged);
  poll();
}

function rollIfChanged(data) {
  if (data > currentTotal) {
    window.clearTimeout(idleTimeout);
    // interface naar jouw code:
    cStart = currentTotal;
    cEnd = data;
    doTimer();
    // pas de else-tak van jouw timedCount aan:
    // daar roep je poll() aan.
  }
}

function withTotalDo(func) {
  $.get('get_amount.php', func);
}

function showStartValue(data) {
  $('#startValue').html(data);
  currentTotal = data;
}



[size=xsmall]Toevoeging op 20/12/2010 11:21:13:[/size]

Heeft iemand enig idee waarom de <span id="txt"> de timer niet toont?

Gebruik jquery, en dan niet meer document.getelementbyid. Maar je probeert nu ook een attribuut van de span te wijzigen! .value is een attribuut. Gebruik .html van jquery.
Yugh, ik zie langzamerhand door de bomen het bos niet meer....

Ik heb jouw spoiler geprobeerd aan mijn script toe te voegen maar er verandert niets.

Als ik naar jouw spoiler kijk dan begint het me te duizelen voor mijn ogen. Waar ik mijn eigen script enigszins begon te begrijpen, snap ik er echt helemaal niets meer van als ik naar jouw spoiler kijk.

Is het mogelijk om te kijken of we in mijn script van 20/12/2010 09:46:21 een aantal aanpassingen kunnen doen waardoor het gaat werken? Dan kunnen we vervolgens kijken of we het 'netter' kunnen maken. Ik heb om de een of andere reden het idee dat mijn script wel werkend is te krijgen. Of denk jij daar anders over?
doe een verwijzing naar het id:

$("#startValue").html(cStart);

Over mijn "spoiler": Het is ook lastige materie hoor, twee telcycli, asynchrone oproepen. Blijf vooral kalm.

Eerst werken, dan netjes; dat is een redelijke aanpak, vooropgesteld dat je die tweede stap wel braaf zet.
Bas Cost Budde op 20/12/2010 11:57:44

doe een verwijzing naar het id:
$("#startValue").html(cStart);
Zie mijn hieronder bijgevoegde script. Ik heb overal deze nieuwe benadering toegepast. Het werkt goed voor cStart en cEnd, maar niet voor de #displayCounter. De counter (althans het startgetal) wordt niet in de counter weergegeven. Wat ik heel raar vind.

Bas Cost Budde op 20/12/2010 11:57:44

Over mijn "spoiler": Het is ook lastige materie hoor, twee telcycli, asynchrone oproepen. Blijf vooral kalm.
Ik adem een paar keer diep in en uit...

Bas Cost Budde op 20/12/2010 11:57:44

Eerst werken, dan netjes; dat is een redelijke aanpak, vooropgesteld dat je die tweede stap wel braaf zet.
Als ik het andersom doe dan verlies ik gegarandeerd het overzicht...

Ok, dit is dus wat ik tot nog toe heb:

<html>
<head>
<script src="js/jquery-1.4.4.min.js" type="text/javascript"></script>
<script type="text/javascript">

var cStart;
var t;
//var timer_is_on=0;
var cEnd;

function startCount()
{
	// Beginwaarde en eindwaarde ophalen
	timerStartValue();
	timerEndValue();
	timerCounterValue();

	// Timer starten
	timedCount();

	// Na 10 seconden controleren of de cEnd is gewijzigd.
	setTimeout("checkEndValue()",10000);
}

function checkEndValue()
{
	// Oude timerEndValue opslaan
	cEndOld=cEnd;
	
	// Nieuwe timerEndValue opvragen
	timerEndValue();

	// Oude en nieuw timerEndValue met elkaar vergelijken
	if(cEndOld!=cEnd){
		// Teller opnieuw starten
		timedCount();
	} else {
		// Over 10 seconden weer controleren
		setTimeout("checkEndValue()",10000);
	}
}

function timedCount()
{
	$("#displayCounter").html(cStart); // Waarde in HTML object plaatsen

	cStart=cStart+1; // Wat moet er met de waarde gebeuren
	
	if(cStart<=cEnd) // Stoppen wanneer de Timer op cEnd staat
	{
		// Functie aanroepen (oneindige loop)
		t=setTimeout("timedCount()",1000);
	}
}

function timerStartValue()
{
	$.get('get_amount.php',
		function(data)
		{
			cStart = data - 10;

			// Beginwaarde tonen
			$("#startValue").html(cStart);
		}
	);
}

function timerEndValue()
{
	$.get('get_amount.php',
		function(data)
		{
			cEnd = data;

			// Eindwaarde tonen
			$("#endValue").html(cEnd);
		}
	);
}

</script>
</head>

<body>

<script type="text/javascript">
// Uitvoeren
window.onload=startCount();

</script>

<p>De startwaarde is <span id="startValue"></span></p>
<p>De eindwaarde is <span id="endValue"></span></p>
<p>De timer staat nu op: <span id="displayCounter"></span></p>

</body>
</html>

De beginwaarde (=database SUM - 10) wordt netjes weergegeven en ook de eindwaarde (=database SUM huidig) wordt netjes weergegeven. Waarom is de beginwaarde - 10 vraag je je nu af? Nou, wanneer er een bezoeker op de website komt wil ik dat de teller eerst vanaf SUM-10 naar de SUM toe telt. Zo ziet de bezoeker dat het een dynamische teller is en geen statische. Later (bij livegang) wordt dit vergroot naar SUM -100. Vervolgens moet dus 10 seconden later worden gekeken of er een verandering in de SUM is en de teller weer gaan lopen. Is er geen wijziging in de SUM? Dan over 10 seconden weer checken.

Reageren