Bonjour,
je viens de rédiger une page .php .html .css et .js qui fonctionne bien avec son compteur de like. À chaque clic sur un like, la page se recharge et affiche le nombre global incrémenté de +1.

Toutefois, je cale sur la possibilité d'offrir au visiteur plusieurs like différents et donc plusieurs valeurs différentes en un seul clic : au choix +1, +3, +5, ou +50 pour incrémenter d'autant le compteur global.

Voici le code, où vous verrez qu'un .mp3 est joué à chaque like, et qu'il est différent selon tel ou tel like, et qu'au terme du .mp3 la page se recharge automatiquement pour incrémenter :
<!doctype html>

<html lang="fr">

<head>

<meta charset="utf-8" />

<meta http-equiv="Content-Language" content="fr" />

<head>

<title>Un compteur de like à ...</title>

<style>

body{
font-family:'Verdana', 'Courrier New', monospace;
background:#b1b1af}

h2{
font-weight:normal;
font-family:MountainsofChristmas-Regular;
font-size:2.3em;
margin-bottom:15px}

#global{
width:600px;
margin:21px auto;
padding:21px 21px 36px 21px;
background:#fff;
text-align:center}

#anim{
display:block;
position:relative;
width:600px;
height:450px;
background:#eee}

#liste{
display:bloc;
margin-bottom:36px}

#liste a{
display:inline-block;
position:relative;
width:118px;
padding:4px 6px;
background:#69674e;
cursor:pointer;
text-decoration:none;
color:#fff;
margin-right:1px;
font-size:2em}

#liste a span{
display:inline-block;
position:absolute;
top:48px;
left:0;
width:118px;
min-width:118px;
font-size:.4em;
background:#69674e;
color:#fff;
padding:4px 6px;
opacity:0;
visibility:hidden;
-webkit-transition:opacity .5s,visibility .5s;
-moz-transition:opacity .5s,visibility .5s;
-ms-transition:opacity .5s,visibility .5s;
-o-transition:opacity .5s,visibility .5s;
transition:opacity .5s,visibility .5s}

#liste a:hover span{
display:inline-block;
visibility:visible;
opacity:1;
-webkit-transition:opacity .5s ease-in-out;
-moz-transition:opacity .5s ease-in-out;
-ms-transition:opacity .5s ease-in-out;
-o-transition:opacity .5s ease-in-out;
transition:opacity .5s ease-in-out}

#liste i{
font-size:.5em}

@font-face{
font-family: MountainsofChristmas-Regular;
src: url("fonts/MountainsofChristmas-Regular.ttf");
font-display: auto}


</style>

</head>

<body>

<div id="global">

<div id="anim">
</div>

<div id="liste">

<h2>
Offrez autant de like que vous le désirez !
</h2>

<p>
<a id="b1" href="sons/b1.mp3">+1 <i>like</i><span>xxxxx</span></a><a id="b2" href="sons/b2.mp3" style="background:#87583f">+3 <i>like</i><span>xxxxx</span></a><a id="b3" href="sons/b3.mp3"style="background:#a54830">+5 <i>like</i><span>xxxxx</span></a><a id="b4" href="sons/b4.mp3" style="background:#c33a21">+50 <i>like</i><span>xxxxx</span></a>

<audio id="player" style="margin-top:18px">
<source src="sons/b1.mp3"></source>
</audio>
</p>

</div>

<?php
if(file_exists('compteur_pages_vues.txt'))
{
$compteur_f = fopen('compteur_pages_vues.txt', 'r+');
$compte = fgets($compteur_f);
}
else
{
$compteur_f = fopen('compteur_pages_vues.txt', 'a+');
$compte = 0;
}
$compte +=1;

//$compte=$compte +=3;
//$compte=$compte +=5;
//$compte=$compte +=50;

fseek($compteur_f, 0);
fputs($compteur_f, $compte);
fclose($compteur_f); 
echo '<p><span style="font-size:5em;font-family:MountainsofChristmas-Regular">'.$compte.'</span><br><i style="display:inline-block;position:relative;margin-top:-12px">global like</i></p>';
?>

</div>

<script>

var liste=document.getElementById('liste'),
player=document.getElementById('player'),
links = liste.getElementsByTagName('a');

for (var i=0; i<links.length; i++) {links[i].addEventListener('click', handler)}

	function handler(e)
{
e.preventDefault();
cible = this.getAttribute('href');
filename = cible.substr(0, cible.lastIndexOf('.')) || cible;
audio = document.querySelector('#liste audio');
source = document.querySelectorAll('#liste audio source');
source[0].src = filename + '.mp3';
audio.load();
player.play();
player.onended=function(){window.location.reload()};
}

</script>

</body>

</html>

Auriez-vous une idée pour intégrer différentes valeurs au $compte ? Merci d'avance ...
Modifié par Gout-de-l-esprit (24 Oct 2021 - 09:20)
Bonjour Niuxe,
je vais tenter de m'expliquer.

1. J'ai quatre <a>...</a> de like que je propose au visiteur.

2. Chaque <a>...</a> propose un nombre distinct : 1, 3, 5 puis 50 like. Au clic sur chacun, on joue un .mp3 qui dure graduellement plus longtemps. Au terme de la lecture de chaque .mp3 la page est rechargée automatiquement : ceci incrémente +1 le global like (le compteur de like).

3. Or, je souhaite ajuster l'incrémentation à chacun des nombres proposés : +1, +3, +5 ou +50
C-à-d :
<a>+1 like</a> -> incrément +1 -> $compte +=1
<a>+3 like</a> -> incrément +3 -> $compte +=3
<a>+5 like</a> -> incrément +5 -> $compte +=5
<a>+50 like</a> -> incrément +50 -> $compte +=50

4. Là précisément je cale, ne sachant pas comment récupérer les différents nombres pour les affecter au global like (compteur) à chaque clic sur chacun des <a>...</a>

5. Même si mon bout de code .php pourrait être modifié ou simplifié, cela fonctionne très bien actuellement, mais le compteur n'est incrémenté que de +1. C'est le pourquoi de ma question.

6. Comment faire ? Une piste, par un data-value dans chacun des <a>...</a> que le .php récupère par une boucle javascript sur les quatre <a>...</a> ?
Modifié par Gout-de-l-esprit (24 Oct 2021 - 21:51)
Modérateur
Sans filet de sécurité (est ce que le fichier existe ? les droits sur le fichier ? etc.). À toi de gérer ça.


counter.txt

0



index.php

<p>
        <a href="manage_counter.php?more=1">+1</a>
        <a href="manage_counter.php?more=3">+3</a>
        <a href="manage_counter.php?more=5">+5</a>
        <a href="manage_counter.php?more=50">+50</a>
</p>
<p><?= file_get_contents('counter.txt') ?></p>


manage_counter.php

<?php
    if(!empty($_GET['more'])){
        $source = 'counter.txt';
        $count = intval(file_get_contents($source));

        $result = intval($_GET['more']) + $count;
        file_put_contents($source, $result);
        header('location:'.$_SERVER['HTTP_REFERER']);
    }
?>


En complément :
- envoyer des paramètres dans l'url
- http_build_query()
Modifié par niuxe (24 Oct 2021 - 17:02)
Je te remercie pour ta proposition : je regarderai cela très vite, puis reviendrai vers toi.

Notes
1. Je veillerai à la protection et à la sécurité d'accès au fichier .txt (si c'est bien ce que tu crains).
2. Dans ta proposition, l'appel aux .mp3 a disparu.

J'en dis un peu plus de mon projet : nous avons tous quelqu'un qui nous est très cher (surtout en cette période troublée voire délétère). Mon projet consiste à permettre à quiconque d'adresser (anonymement) des like +1, +3, +5 ou +50 à la personne chérie (le dislike est ignoré, ce n'est pas ici le débat). Quatre différents .mp3 de "bisous" tendres et délirants sont aussi importants à favoriser ... que le global like (compteur) puisse en présenter l'expression juste et logique.
upload/1635111052-83754-bisou.png
Modifié par Gout-de-l-esprit (24 Oct 2021 - 23:31)
Modérateur
en faisant un peu mieux :

- Dans ce système, si on trafique l'url, le compteur n'affichera pas d'incrémentation douteuse Smiley cligne . C'est une petite protection qui devrait être efficace
- ajout d'une requête ajax. Ce qui veut dire, que tu peux lancer ton mp3 au retour probant de la requête ajax Smiley cligne
- si le compteur n'existe pas, il sera créé et sa valeur sera de 0 par défaut.


index.php

<?php
    $salt = "counterlike";
    $data = [
        1,
        3,
        5, 
        50
    ];
    $path_controller = "manage_counter.php";
    $counter_file = 'counter.txt';

?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <p id="counter-view">
        <?php foreach ($data as $i => $v): ?>
        <?php 
            $query_string = http_build_query([
                'more' => $v,
                'sec' => md5($salt.dirname($_SERVER['PHP_SELF']).'/'.$path_controller.'more'.$v)
            ]);
        ?>
        <a href="<?= $path_controller ?>?<?= $query_string ?>">+<?= $v ?></a>
        <?php endforeach; ?>
    </p>

    <p id="result"><?= file_exists($counter_file)? file_get_contents($counter_file) : '0' ?></p>

    <script>
window.addEventListener('DOMContentLoaded', () =>{
    document.querySelectorAll('#counter-view a').forEach($a =>{
        $a.addEventListener('click', e=>{
            e.preventDefault();
            let xhr = new XMLHttpRequest();
            xhr.open("GET", $a.href, true);
            xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
            xhr.addEventListener('readystatechange', ev =>{
                if(xhr.readyState == 4 && xhr.status == 200) {
                    if(/^\d+$/.test(xhr.responseText)){
                    document.getElementById('result').textContent = xhr.responseText;
                    }
                }
            });
            xhr.send();
        });
    });
});
    </script>

</body>
</html>


manage_counter.php

<?php
    if(!empty($_GET['more']) && !empty($_GET['sec'])){
        $salt = "counterlike";        
        $confirm = md5($salt.dirname($_SERVER['PHP_SELF']).'/'.basename($_SERVER['PHP_SELF']).'more'.$_GET['more']);

        if($confirm === $_GET['sec']){
            $more = intval($_GET['more']);
            $source = 'counter.txt';
            if(!file_exists($source)){
                touch($source);
                chmod($source, 0666);
                file_put_contents($source, 0);
            }
            $count = intval(file_get_contents($source));
            $result = intval($_GET['more']) + $count;
            file_put_contents($source, $result);
            if("XMLHttpRequest" === $_SERVER['HTTP_X_REQUESTED_WITH']){
                echo $result; die;
            }
        }
        header('location:'.$_SERVER['HTTP_REFERER']);        
    }
?>

Modifié par niuxe (25 Oct 2021 - 01:49)
Ça marche vraiment bien !

Toutefois, dans la partie de ton code que je reprends ci-dessous, je ne suis pas parvenu à attribuer à chacun des <a>...</a> leur .mp3 respectif.

Certes, le lecteur <audio> démarre au clic sur tous les <a>...</a> mais sans solution que j'aurais pu trouver pour les distinguer et leur attribuer ainsi leur .mp3.

La bonne fée magique n'est pas parvenue à m'inspirer ce matin, car si je lance une boucle for sur les 4 <a>...</a> désormais affichés cela semble affecter ton mécanisme en faisant recharger la page :

<audio id="player" controls>
<source src="sons/b4.mp3"></source>
</audio>


    <script>
window.addEventListener('DOMContentLoaded', () =>{
    document.querySelectorAll('#counter-view a').forEach($a =>{
        $a.addEventListener('click', e=>{
            e.preventDefault();
            let xhr = new XMLHttpRequest();
            xhr.open("GET", $a.href, true);
            xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
            xhr.addEventListener('readystatechange', ev =>{
                if(xhr.readyState == 4 && xhr.status == 200) {
                    if(/^\d+$/.test(xhr.responseText)){
                    document.getElementById('result').textContent = xhr.responseText;
                    }
                }
            });
            xhr.send();
Play();
        });
    });
});

var player = document.getElementById('player');
player.load();

	function Play()
{
player.play();
}

    </script>

Modifié par Gout-de-l-esprit (25 Oct 2021 - 09:40)
Heu ! c'est simple ?

J'ai tenté beaucoup, mais je reste calé : ne souhaitant qu'un lecteur <audio>, je ne sais toujours pas comment lui attribuer le bon .mp3 au choix.

En fait, au clic sur chacun des <a>, je ne parviens pas à reconnaître un <a> cliqué ... (ou survolé pour un .css : a:hover span{} et texte différent dans les <span>).

Quelque chose m'échappe dans ton mécanisme parfait, là où je pourrais agir sur la bonne chose !

Quoi que la solution m'apparaîtra lumineuse, elle viendra à posteriori évidemment ...
Modifié par Gout-de-l-esprit (26 Oct 2021 - 03:12)
Modérateur
&lo,

Pour te mettre sur la voie :

... 
....forEach($a =>{
$a.addEventListener('click', ....
....
if(/^\d+$/.test(xhr.responseText)){
... 
// ton code ici !!
}
...


Je t'invite à lire ou relire la doc sur la méthode forEach()

edit:
Accessoirement, tu pourrais même utiliser un dataset comme solution alternative pour lancer le chargement et la lecture de ton audio
Modifié par niuxe (26 Oct 2021 - 13:56)
Merci Niuxe,
j'ai tenté ceci, mais sans succès (et cela fait recharger la page, ce n'est qui pas escompté !) :
<audio id="player" controls>
<source src=""></source>
</audio>

 <script>
window.addEventListener('DOMContentLoaded', () =>{
    document.querySelectorAll('#counter-view a').forEach($a =>{
        $a.addEventListener('click', e=>{
            e.preventDefault();
            let xhr = new XMLHttpRequest();
            xhr.open("GET", $a.href, true);
            xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
            xhr.addEventListener('readystatechange', ev =>{
                if(xhr.readyState == 4 && xhr.status == 200) {
                    if(/^\d+$/.test(xhr.responseText)){

var playersource = document.querySelectorAll('#player audio source');
var src = playersource.src;
var counter-view = document.getElementById('counter-view');
var x = counter-view.getElementsByTagName('a');
if (x[0]) {src='sons/b1.mp3'}
else if (x[1]) {src='sons/b2.mp3'}
else if (x[2]) {src='sons/b3.mp3'}
else if (x[3]) {src='sons/b4.mp3'};

var player = document.getElementById('player');
player.play();

                    document.getElementById('result').textContent = xhr.responseText;
                    }
                }
            });
            xhr.send();
        });
    });
});

    </script>


J'ai également tenté d'inclure ma proposition quelques accolades-fermées plus loin (ceci me semblait logique), mais en vain.

Je crains d'avoir la tête un peu ailleurs, en ce moment ... Je suis certainement déconcentré. Or je reviendrai vite avec une attention bien meilleure. Entretemps, quelqu'un pourrait-il proposer une solution ?
Modifié par Gout-de-l-esprit (26 Oct 2021 - 22:35)
Modérateur
Gout-de-l-esprit a écrit :

...(et cela fait recharger la page, ce n'est qui pas escompté !) :

pierre giraud a écrit :

....
Concernant le nom de nos variables, nous avons une grande liberté dans le nommage de celles-ci mais il y a quand même quelques règles à respecter :

Le nom d’une variable doit obligatoirement commencer par une lettre ou un underscore (_) et ne doit pas commencer par un chiffre ;
Le nom d’une variable ne doit contenir que des lettres, des chiffres et des underscores mais pas de caractères spéciaux ;
Le nom d’une variable ne doit pas contenir d’espace.

De plus, notez que le nom des variables est sensible à la casse en JavaScript. Cela signifie que l’usage de majuscules ou de minuscules avec un même nom va permettre de définir des variables différentes. Par exemple, les noms texte, TEXTE et tEXTe vont pouvoir définir des variables différentes.
....


Ce qui veut dire que le kebab case n'est pas admis.



Gout-de-l-esprit a écrit :
Entretemps, quelqu'un pourrait-il proposer une solution ?

niuxe a écrit :
Je t'invite à lire ou relire la doc sur la méthode forEach()
edit:
Accessoirement, tu pourrais même utiliser un dataset comme solution alternative pour lancer le chargement et la lecture de ton audio

Modifié par niuxe (27 Oct 2021 - 09:03)
Bon ! j'ai ceci qui fonctionne enfin :
<audio id="player" controls>
<source src=""></source>
</audio>

<script>

window.addEventListener('DOMContentLoaded', () =>{
    document.querySelectorAll('#counterview a').forEach($a =>{
        $a.addEventListener('click', e=>{
            e.preventDefault();
            let xhr = new XMLHttpRequest();
            xhr.open("GET", $a.href, true);
            xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
            xhr.addEventListener('readystatechange', ev =>{
                if(xhr.readyState == 4 && xhr.status == 200) {
                    if(/^\d+$/.test(xhr.responseText)){
Play();
                    document.getElementById('result').textContent = xhr.responseText;
                    }
                }
            });
            xhr.send();
        });
    });
});

	function Play()
{
var player = document.getElementById('player');
var counterview = document.getElementById('counterview');
var x = counterview.getElementsByTagName('a');

x[0].onclick = function(){player.setAttribute("src", "sons/b1.mp3")};
x[1].onclick = function(){player.setAttribute("src", "sons/b2.mp3")};
x[2].onclick = function(){player.setAttribute("src", "sons/b3.mp3")};
x[3].onclick = function(){player.setAttribute("src", "sons/b4.mp3")}; 

player.load();
player.play();
}

</script>


Merci Niuxe pour ta sollicitude harmonieuse (sauf que l'appel à un nouveau forEach que j'ai mené a toujours présenté un conflit comme doublon de ton écriture ; j'ai donc procédé autrement ...).

Par la solution que je présente, existe un phénomène d'inertie qui impose que le premier clic pour lancer n'importe quel .mp3 soit inopérant : je ne sais pas comment le résoudre par un init() ...

Enfin, il me reste à gérer les 4 <a>...<span>...</span></a> (.css avec background-image:linear-gradient(to right, #..., #...). Car là ça devient compliqué avec les écritures .php actuelles.

En effet, cela ne serait-il pas préférable de démarrer le .php sur l'existence des 4 <a> en clair dans le .html, lesquels effectivement proposeraient, par exemple des data-nb="1" data-nb="3" data-nb="5" data-nb="50" comme indicateurs de like variable ?

Si l'envie vous en dit ...
Je viens de résoudre la question de l'inertie du premier clic au lancement de n'importe quel .mp3 :
...
window.onload=Play;

</script>
Modérateur
et l'eau gout de l'esprit,

ta solution doit peut-être fonctionner. Mais elle n'est pas du tout performante. Tu déclares 2 écouteurs pour un même élément. Or, pour le coup et pour un même écouteur, tu peux cumuler :
- incrémentation du compteur
- jouer le son


<audio id="audio"></audio>



...
.forEach(($a, i) =>{
....
if(/^\d+$/.test(xhr.responseText)){
    document.getElementById('result').textContent = xhr.responseText;
    let $audio = document.getElementById('audio');
    $audio.pause();
    $audio.src = `chemin/vers/b${i + 1}.mp3`;
    $audio.play();
}


1. tu n'as pas besoin d'un init
2. tu envoies à la volée la lecture d'un mp3
3. tu utilises un seul écouteur
4. tu utilises le système d'index qu'offre la méthode forEach. Il ne faut pas oublier que c'est une méthode pour boucler/loop

Comme je te l'ai conseillé, il est peut-être plus pertinent d'utiliser un dataset. Tout dépend du contexte.

**attention** : il est peut-être préférable de préloader ton audio. Dans ce cas tu déclares plusieurs <audio> en html et en js, tu vas les chercher. exemple :

<audio id="audio_0" src="b1.mp3" preload></audio>
<audio id="audio_1" src="b2.mp3" preload></audio>
<audio id="audio_2" src="b3.mp3" preload></audio>
<!-- etc. -->


Pour finir, si tu estimes que le sujet est résolu, indique le dans le forum en cochant la case "résolu"
Modifié par niuxe (28 Oct 2021 - 10:06)
Juste avant de marquer le sujet comme résolu, je pose une dernière question : quelle peut être la différence déterminante entre les deux apostrophes suivantes ?
`
et
'
car avec les tiennes ` tout fonctionne (!) mais avec les miennes ' : non !

J'avais lu quelque chose sur la chose, jadis il y a bien longtemps sur Alsa mais que je ne parviens pas à retrouver ...

Or voici que cette énigme s'impose à moi. C'est dingue, non ?
Modifié par Gout-de-l-esprit (28 Oct 2021 - 15:14)
Quoi qu'il en soit : après quelque aménagement .css sur les a:nth-child(n){},
n=1, 2, 3, 4
le résultat est performant
upload/1635439751-83754-bisous.png

Merci ! et bravo Niuxe,
je marque le sujet comme résolu.
Modifié par Gout-de-l-esprit (28 Oct 2021 - 18:56)