# Bis zu einer bestimmten Zahl hochzählen



## fawin (29. August 2020)

Hallo zusammen,

für die Homepage unseres Vereins suche ich die Möglichkeit bin zu einer Zahl hochzuzählen. Es geht darum darzustellen, wie viele Personen sich für eine Veranstaltung angemeldet haben.

Das hochzählen bin zu einer "festen" Zahl funktioniert auch mit diesem Script super:


Spoiler





```
<html>
<body>
<script>
var i = 0;

var inv = setInterval(function() {    
    if(i < 250)
        document.getElementById("counter").innerHTML = ++i;
    else
        clearInterval(inv);
}, 3000 / 100);
</script>

Soviele sind dabei <span id="counter"></span>

</body>
</html>
```




Die Anmeldezahl bekommen wir von einem externen Anbieter, der die Anmeldungen abwickelt. Er übergibt uns diese Zahl über seine API als URL. Mit _der php-Funktion file_get_contents _bekomme ich die Zahl auch ausgegeben.


Spoiler





```
<?php
$anmeldungen = file_get_contents('https://api.raceresult.com/132677/2LOCB05PVRFATRGW2L3Y9V6B3Z6NB1SE');
echo $anmeldungen;
?>
```




Kann mir jemand helfen, wie ich das Hochzähl-Javascript mit der php-Funktion kombiniere und bis zu der Zahl aus der Variable $anmeldungen hochzähle?

Über eure Hilfe würde ich mich sehr freuen.

Vielen Dank und viele Grüße

Fabian


----------



## basti1012 (30. August 2020)

Verstehe gerade nicht wo du genau hilfe brauchst ?
Du hast ja alles was du brauchst.
Zb so

```
<html>
<body>
<div>Soviele sind dabei <span id="counter"></span></div>
<script>
var i = <?php echo file_get_contents('https://api.raceresult.com/132677/2LOCB05PVRFATRGW2L3Y9V6B3Z6NB1SE'); ?>;
setInterval(function(){    
    if(i < 250){
        document.getElementById("counter").innerHTML = ++i;
    }else{
        clearInterval(inv);
    }
},30);
</script>
</body>
</html>
```
Nicht die schönste Lösung ,aber geht.
Jenachdem was du genau vor hast kann man es noch ändern.
Oder willst du das dies Script alle X Sekunden eine Abfrage aus der API macht?
Jetzt öffnest du ja die Seite und er zählt von da aus weiter, was in der API steht.
Wozu soll das hochzählen sein?
Bei so ein Intervall ist das ja egal, ob er bei 1 oder 200 Startet, weil er in wenigen Sekunden sowieso beim Ende angekommen ist?
Wenn die API ja die aktuellen Zahlen ausgibt, wozu zählst du dann hoch?
Für aktuelle Zahlen brauch man ja nur die API neu Anzeigen?
Eine genauere Erklärung könnte uns helfen dir eine bessere Lösung zu zeigen


----------



## fawin (30. August 2020)

@basti1012: Vielen Dank für deine Antwort!

Das geht schon in die richtige Richtung. Dein Script zählt ja von der Zahl aus _file_get_contents_ bis 250 hoch.

Meine Idee war, dass das Script von 0 bis zur Zahl aus _file_get_contents_ hochzählt. Also quasi in dem Fall von 0 bis 107, der aktuellen Zahl der Anmeldungen.

Ich habe schon versucht es zu ändern, bekomme es aber nicht hin...
Wenn das Script grundsätzlich nicht ideal ist, gerne verbessern. 


Vielen Dank und viele Grüße


----------



## basti1012 (30. August 2020)

fawin hat gesagt.:


> Meine Idee war, dass das Script von 0 bis zur Zahl aus _file_get_contents_ hochzählt. Also quasi in dem Fall von 0 bis 107, der aktuellen Zahl der Anmeldungen.
> 
> Ich habe schon versucht es zu ändern, bekomme es aber nicht hin...


Da brauchst du ja nur die if Abfrage ändern

```
<html>
<body>
<div>Soviele sind dabei <span id="counter"></span></div>
<script>
var i=0;
var ende = <?php echo file_get_contents('https://api.raceresult.com/132677/2LOCB05PVRFATRGW2L3Y9V6B3Z6NB1SE'); ?>;
setInterval(function(){   
    if(i < ende){
        document.getElementById("counter").innerHTML = ++i;
    }else{
        clearInterval(inv);
    }
},30);
</script>
</body>
</html>
```


----------



## fawin (30. August 2020)

@basti1012: Vielen Dank, das funktioniert prima!

Leider haut es Script durcheinander, wenn ich mehrere Zahlen ausgeben möchte.

Wir haben nämlich 3 Distanzen/Wettbewerbe. Wenn ich das Script stumpf (zu mehr reicht es leider nicht) erweitere, kommen komische Sachen raus.

Ich habe mal eine Test php-Seite gebaut:



Spoiler





```
<html>
<body>
<p>Anmeldungen lange Strecke: <span id="counter_langstrecke"></span> (<?php echo file_get_contents('https://api.raceresult.com/132677/2LOCB05PVRFATRGW2L3Y9V6B3Z6NB1SE'); ?> laut API)</p>
<p>Anmeldungen mittlere Strecke: <span id="counter_mittelstrecke"></span> (<?php echo file_get_contents('https://api.raceresult.com/132677/WKFBVLOQZ3ZG8YBYR81OIYJU4XUIOR7J'); ?> laut API)</p>
<p>Anmeldungen kurze Strecke: <span id="counter_kurzstrecke"></span> (<?php echo file_get_contents('https://api.raceresult.com/132677/2QATF4ST0I0OMVDRN83DUKB2D0MWF871'); ?> laut API)</p>
<script>
var i=0;
var ende = <?php echo file_get_contents('https://api.raceresult.com/132677/2LOCB05PVRFATRGW2L3Y9V6B3Z6NB1SE'); ?>;
setInterval(function(){   
    if(i < ende){
        document.getElementById("counter_langstrecke").innerHTML = ++i;
    }else{
        clearInterval(inv);
    }
},30);
</script>
<script>
var i=0;
var ende = <?php echo file_get_contents('https://api.raceresult.com/132677/WKFBVLOQZ3ZG8YBYR81OIYJU4XUIOR7J'); ?>;
setInterval(function(){   
    if(i < ende){
        document.getElementById("counter_mittelstrecke").innerHTML = ++i;
    }else{
        clearInterval(inv);
    }
},30);
</script>
<script>
var i=0;
var ende = <?php echo file_get_contents('https://api.raceresult.com/132677/2QATF4ST0I0OMVDRN83DUKB2D0MWF871'); ?>;
setInterval(function(){   
    if(i < ende){
        document.getElementById("counter_kurzstrecke").innerHTML = ++i;
    }else{
        clearInterval(inv);
    }
},30);
</script>
</body>
</html>
```




Oder ist das Script doch nicht geeignet für mein Vorhaben?

Viele Grüße


----------



## basti1012 (30. August 2020)

dann versuche es mal mit *nicht* gleichen Varabeln ( *i *und* ende )*.
Nehme dafür i,o,u und ende1 ende2 und ende3 oder sonst irgendwas.
Dann sollte es wohl schon gehen.

Du must bei clearInterval die Variable *inv *noch irgendwo zuordnen ( vor setInterval ) , das hatte ich beim kopieren irgendwie falsch gemacht.


----------



## fawin (30. August 2020)

@basti1012: Nochmals vielen Dank für deine Hilfe!   So funktioniert es fast perfekt.

Einen letzten Wunsch hätte ich noch, ist es möglich, dass alle Counter gleichzeitig "fertig werden" ?

So sieht mein Code momentan aus:


Spoiler





```
<html>
<body>
<p>Anmeldungen lange Strecke: <span id="counter_langstrecke"></span> (API: <?php echo file_get_contents('https://api.raceresult.com/132677/2LOCB05PVRFATRGW2L3Y9V6B3Z6NB1SE'); ?>)</p>
<p>Anmeldungen mittlere Strecke: <span id="counter_mittelstrecke"></span> (API: <?php echo file_get_contents('https://api.raceresult.com/132677/WKFBVLOQZ3ZG8YBYR81OIYJU4XUIOR7J'); ?>)</p>
<p>Anmeldungen NW: <span id="counter_nw"></span> (API: <?php echo file_get_contents('https://api.raceresult.com/132677/55QUXU4V277DTY9GF574RV3GUUL28M1I'); ?>)</p>
<p>Anmeldungen kurze Strecke: <span id="counter_kurzstrecke"></span> (API: <?php echo file_get_contents('https://api.raceresult.com/132677/2QATF4ST0I0OMVDRN83DUKB2D0MWF871'); ?>)</p>

<script>/* lange strecke */
var i=0;
var ende1 = <?php echo file_get_contents('https://api.raceresult.com/132677/2LOCB05PVRFATRGW2L3Y9V6B3Z6NB1SE'); ?>;
setInterval(function(){   
    if(i < ende1){
        document.getElementById("counter_langstrecke").innerHTML = ++i;
    }else{
        clearInterval(inv);
    }
}, 3000 / 100);
</script>

<script>/* mittlere strecke */
var o=0;
var ende2 = <?php echo file_get_contents('https://api.raceresult.com/132677/WKFBVLOQZ3ZG8YBYR81OIYJU4XUIOR7J'); ?>;
setInterval(function(){   
    if(o < ende2){
        document.getElementById("counter_mittelstrecke").innerHTML = ++o;
    }else{
        clearInterval(inv);
    }
}, 3000 / 100);
</script>

<script>/* NW */
var n=0;
var ende4 = <?php echo file_get_contents('https://api.raceresult.com/132677/55QUXU4V277DTY9GF574RV3GUUL28M1I'); ?>;
setInterval(function(){   
    if(n < ende4){
        document.getElementById("counter_nw").innerHTML = ++n;
    }else{
        clearInterval(inv);
    }
}, 3000 / 100);
</script>


<script>/* kurze Strecke */
var u=0;
var ende3 = <?php echo file_get_contents('https://api.raceresult.com/132677/2QATF4ST0I0OMVDRN83DUKB2D0MWF871'); ?>;
setInterval(function(){   
    if(u < ende3){
        document.getElementById("counter_kurzstrecke").innerHTML = ++u;
    }else{
        clearInterval(inv);
    }
}, 3000 / 100);
</script>
</body>
</html>
```




Vielen Dank nochmal und viele Grüße


----------



## basti1012 (30. August 2020)

fawin hat gesagt.:


> Einen letzten Wunsch hätte ich noch, ist es möglich, dass alle Counter gleichzeitig "fertig werden" ?


Wie meinst du das den ?
Wenn bei den Apis zb 20, 50, und eine 100 steht , dann sollen beim hochzählen alle gleichzeitig fertig werden ?
Das sollte eigentlich kein problem sein.
Du mußt dann halt nur den setInterval bei jeden Timer anpassen.
Ich muß das mal gerade selber testen.


----------



## basti1012 (31. August 2020)

Ich würde dein jetzigen Code mal so umbauen

```
<?php
$apis=['https://api.raceresult.com/132677/2LOCB05PVRFATRGW2L3Y9V6B3Z6NB1SE',
'https://api.raceresult.com/132677/WKFBVLOQZ3ZG8YBYR81OIYJU4XUIOR7J',
'https://api.raceresult.com/132677/55QUXU4V277DTY9GF574RV3GUUL28M1I',
'https://api.raceresult.com/132677/2QATF4ST0I0OMVDRN83DUKB2D0MWF871'];
$apiausgabe=[];
for($r=0;$r<=count($apis)-1;$r++){
    array_push($apiausgabe, file_get_contents($apis[$r]));
}
?>
<html>
   <body>
      <p>Anmeldungen lange Strecke: <span id="counter0"></span></p>
      <p>Anmeldungen mittlere Strecke: <span id="counter1"></span></p>
      <p>Anmeldungen NW: <span id="counter2"></span></p>
     <p>Anmeldungen kurze Strecke: <span id="counter3"></span></p>
<script>
var js_array =<?php echo json_encode($apiausgabe);?>;
console.log(js_array);
var counterlaufzeit=2000;//millisekunden
i=0;
function start(h,i){
   const ms=counterlaufzeit/js_array[h];
   if(i<js_array[h]){
     setTimeout(function(){
         i++
         document.getElementById('counter'+h).innerHTML=i+' ( API '+js_array[h]+' )';
         start(h,i);
     },ms.toFixed(2));
   }
}
start(0,i);
start(1,i);
start(2,i);
start(3,i);
</script>
</body>
</html>
```
*Warum* habe ich deinen Code geändert?
1. So muss man den Parser nicht unnötig quälen mit den rein (*<?php*) und raus (*?>*) gehen.
Das macht bei so einen kleinen Code nicht viel aus , aber Kleinvieh macht auch Mist.
2. So sparst du *4 x file_get_contents().*
3. Der Code lässt sich so ohne Probleme erweitern (nicht das beste Argument).
4. JS Code ist kürzer.
5. Habe gemerkt das clearInterval() blödsinn ist und gar nicht gebraucht wird ,bzw es auch ohne geht.
Vielleicht können sich hier noch andere zu melden wie man die Counter gleichzeitig stoppt.
Die stoppen jetzt so auf wennige Millisekunden gleichzeitig.
Warum es nicht gleichzeitig ist verstehe ich auch noch nicht ganz.
Bin kein Rechen Genie.


----------



## fawin (1. September 2020)

@basti1012: ... und nochmal vielen vielen Dank für deine Hilfe! 

Das funktioniert hier prima

(Da du alles schön zusammengefasst hast, wird das komplette Script zwar 4x aufgerufen, aber es funktioniert auch so...)

Mit den paar Millisekunden Versatz kann ich auf jeden Fall super Leben.


Vielen Dank nochmal und viele Grüße


----------



## basti1012 (2. September 2020)

Bei dir auf der Seite sind die unterschiede aber größer als paar Millisekunden.
Außerdem nutzt du doppelte ids und das geht eigentlich gar nicht.
Das Script 4 mal einbinden ist auch vollkommen unnötig.
Wieso hast du nicht meine Vorlage benutzt?
Das was du jetzt machst ist Murks.

Ich versuche mal das Script mal etwas zu ändern , auf dein Html passend


----------



## basti1012 (2. September 2020)

So.
Habe das mal geändert.
Habe jetzt auch ein Weg gefunden wie alle Counter gleichzeitig stoppen.
***Link entfernt, weil Seite nicht mehr erreichbar ***

Falls die Kommazahlen nicht erwünscht sind musst du bei .toFixed(2) eine 0 reinschreiben.
Habe dir auf der Seite ganz unten den Code sichtbar eingefügt( mit PHP ).
Wie auch immer du das machen willst musst du wissen , nur wie du es jetzt hast geht es eigentlich gar nicht.
PS du hast da aber auch noch einige Fehler wie ungeschlossenen Elemente,5 Mal body , und so weiter. Das schlimmste ist das mit den Scripten.
Alle 4 Scripte machen auf alle 8 Counter ids das Gleiche. Theoretisch kannst du 3 Scripte löschen und es läuft trotzdem alles noch.
https://validator.w3.org/nu/?doc=https://www.hochsauerlandlauf.de/anmeldungen
Du wirst damit bestimmt noch Probleme bekommen.


----------



## fawin (2. September 2020)

@basti1012: Ich habe dein Script jetzt verwendet und es sollte nun alles wie geplant funtionieren.

Damit sich die beiden Scripte (Streckenlängen hochzählen und Anmeldungen hochzählen) nicht gegenseitig in die Quere kommen, habe ich diese nicht wie bisher global im Template-Footer eingefügt, sondern im body. Somit werden sie nie zusammen aufgerufen.

Vielen Dank nochmal und viele Grüße!


----------



## basti1012 (3. September 2020)

Das sieht aufjedenfall schon mal besser aus.
Auch beim Validator hast du schon mal 50 Errors wenniger.

Du solltest versuchen die anderen Validator Fehler auch noch zu beheben , die meißten davon sind auch nur kleinigkeiten.
Aber schön das das Script jetzt läuft.
Mfg Basti


----------

