Bonjour,
dans le code suivant le bouton0 aurait dû se présenter avec un background "red" or il reste en "skyblue". De plus les fonction "button:hover" et "button:active" ne fonctionnent pas.
Le code HTML est enregistré jusqu'au script dans la mémoire SPIFFS d'un composant ESP8266, puis le reste est chargé dynamiquement par le programme (Arduino) avec les variables.
merci de votre aide car voilà plus d'une semaine que je galère.
Michel


!DOCTYPE html>
<html>
<head>
  <title>ESP8266 Web Server</title>
  <meta  charset="utf-8" name="viewport" content="width=device-width, initial-scale=1">
  <style>
  	p.ex1{
		width: 50px;
		padding: 5px;
		background-color: skyblue;
		display: inline;
		margin: 2px;
  	}
  	p.ex2 {
		width: 50px;
		padding: 5px;
		background-color: red;
		display: inline;
		margin: 2px
  	}
  </style>
</head>
<style>
  html {
    font-family: Arial;
    display: inline-block;
    margin: 0px auto;
    text-align: center;
  }
  h1 {
    color: #0F3376;
    padding: 2vh;
  }
  p {
    font-size: 1.5rem;
  }
  label {
    font-size: 12px;
    margin: 10px;
  }
  .button {
    display:inline;
    border: none;
    border-radius: 4px;
    color: white;
    padding: 6px;
    text-decoration: none;
    font-size: 16px;
    margin: 2px;
    cursor: pointer;
  }
  .button:hover {background-color: green;}
  .button:active {background-color: black;}
  } 
</style>
<script type="text/javascript">	
	function action(num){
	  var msg = "";
	  if (document.getElementById("select" + num).checked==true) {
		msg="/btn" + num +"/pou!";}
	  else {
		msg="/btn" + num + "/non!";}
	  var xhttp = new XMLHttpRequest();
	  xhttp.open("POST","/");
	  xhttp.send(msg);
	}
</script>

<body>
  <h1>ESP8266 Web Server</h1>
  <h2>Etat des commandes lumineuses</h2>
  <div> <p class="ex1">Eteint</p> <p class="ex2">Allumé</p> </div>
  <br></br>
  <p>Appuyer sur la touche désirée</p>
	
<div>
<button type="button" class="button"  style="background-color:red;"[code=html]
onclick= "action(0)">Lum0</button>
<button type="button" class="button" style="background-color:skyblue;" onclick= "action(1)">Lum1</button>
<button type="button" class="button" style="background-color:skyblue;" onclick= "action(2)">Lum2</button>
<button type="button" class="button" style="background-color:skyblue;" onclick= "action(3)">Lum3</button>
</div>
<p style="font-size:10px;">Selection du type de bouton poussoir ou par défaut interrupteur</p><br></br>
<div>
<input type="checkbox" id="select0"><label for = "select0">poussoir1</label>
<input type="checkbox" id="select1"><label for = "select1">poussoir2</label>
<input type="checkbox" id="select2"><label for = "select2">poussoir3</label>
<input type="checkbox" id="select3"><label for = "select3">poussoir4</label>
</div>
</body></html>
[/code]
Ci-après le code Arduino en C/C++

//****************************************************************************************
//******************Essai d'utilisation de la mémoire SPIFFS******************************
//****************Serveur équipé de 4 sorties pour relais interrupteur ou poussoir********
//****************************************************************************************
#include "FS.h"               //****Librairie pour le SPIFFS****
#include <ESP8266WiFi.h>      //****Librairie pour le Wifi de l'ESP8266****

const uint16_t NBBTN = 4;  //****nombre de boutons <=10****
int port[]= {14,12,13,15};
String backColor[NBBTN];
String pageHtml = "";

const char* nomDeFichier = "/index.html";
const char* ssid = "xxxxxxxxxx" //****NOM RESEAU WIFI****
const char* password = "xxxxxxxxxxx"; //****MOT DE PASSE WIFI****
const uint16_t HTTPPort = 80;

int cmpt = 0;
WiFiServer serveur(HTTPPort); // crée un serveur sur le port HTTP standard

//********************************Routine d'affichage des informations de connexion**********
void printHTTPServerInfo(){
  Serial.print(F("Site web  http://"));
 
  Serial.print(WiFi.localIP());
  if (HTTPPort != 80) {
    Serial.print(F(":"));
    Serial.print(HTTPPort);
  }
  Serial.println();
}
//********************************Routine de gestion d'un client*******************************
void testRequeteWeb(){
  String boutonClique = "";
  WiFiClient client = serveur.available();   //****on crée un WiFiClient qui s'appelle client****
  if (client){     //**** client connecté ****
    Serial.print("Acces client N° ");
    Serial.println(++cmpt);
    if (client.connected()) {
      client.setTimeout(500);
      String req = client.readStringUntil('!'); //********* on lit toute la trame HTPP jusqu'au
      Serial.println(req);                      // char '!' qui est la fin du POST envoyé sinon
      client.flush();                           // on attend le timeout de 500 millis**********
      // **********************On envoie une entête de réponse HTTP standard********************
      client.println(F("HTTP/1.1 200 OK"));  //ligne de statut
      client.println(F("Content-Type: text/html\r\n"));  //********champ d'entete **************
      //***********************On teste le POST pour savoir si un bouton a ete appuye**********
      if (req.indexOf("POST")>=0){
        int pos = req.indexOf("/btn");                
        int nBouton = req.substring(pos+4,pos+5).toInt();   //*******Recupere le numero du bouton appuye**
        boutonClique = "<br></br><p>Le bouton N° " + String(nBouton +1) + " est cliqué</p>";
        if(digitalRead(port[nBouton])==HIGH){  //********Mise en condition des elements du bouton**
          digitalWrite(port[nBouton],LOW);
          backColor[nBouton]="skyblue";
        }
        else {
          digitalWrite(port[nBouton],HIGH);
          backColor[nBouton]= "red";
          if (req.substring(pos + 6,pos + 8)=="pou") {
            delay(500);
            digitalWrite(port[nBouton],LOW);
          }
        }
      }
      // **********************On envoie la page contenu dans SPIFFS vers le client*************
      pageHtml="";
      Serial.println(F("Envoi du SPIFFS"));
      if (SPIFFS.exists(nomDeFichier)) {      //****si le fichier SPIFFS existe****
        File pageSPIFFS = SPIFFS.open(nomDeFichier, "r");
        while (pageSPIFFS.available()){          //****on charge la page du SPIFFS dans pageHtml****
          pageHtml += char(pageSPIFFS.read());
        }
        //client.write(pageSPIFFS);   *****permet d'envoyer directement la page SPIFFS vers le client***
         pageSPIFFS.close();        
      } 
      else {          //***********sinon on termine la requête*********************
        Serial.println(F("Erreur de fichier"));              
        client.println("break");      
        return;      
      }
      pageHtml += "<div>\n";
      for (int i=0;i<NBBTN;i++){    //***************mise en forme des boutons avec leur couleur d'etat **************************************************
        pageHtml += "<button class=\"button\"  style=\"background-color:" + backColor[i] + ";\" onclick= \"action("+ String(i) + ")\">Lum" + String(i) + "</button>\n";
      }
      pageHtml += "</div>\n";
      pageHtml += "<p style=\"font-size:10px;\">Selection du type de bouton poussoir ou par défaut interrupteur</p><br></br>\n";
      pageHtml += "<div>\n";
      for (int i=0;i<NBBTN;i++){    //***************mise en forme des checkbox pour poussoir **************************************************
        pageHtml += "<input type=\"checkbox\" id=\"select" + String(i) + "\">";
        pageHtml += "<label for = \"select" + String(i) + "\">" + "poussoir" + String(i+1) + "</label>\n";
      }
      pageHtml += "</div>\n";
      //*****************************************Fin de la page HTML*******************************************************************
      pageHtml += boutonClique;
      pageHtml += "</body></html>";
      delay(1);
      client.println(pageHtml);
      delay(10);
      client.stop(); //**** termine la connexion ****
    }
  }
}
//**************************************************SET UP******************************************************************************
void setup() {
  for(int i=0;i<NBBTN;i++){
    pinMode(port[i],OUTPUT);
    digitalWrite(port[i],LOW);
    backColor[i] = "skyblue"; 
  }
  Serial.begin(115200); //
  Serial.println("\n\nTest SPIFFS\n"); 
  if (!SPIFFS.begin()) {        //********** on démarre le SPIFFS
    Serial.println("erreur SPIFFS");
    while (true); // on ne va pas plus loin
  }

  WiFi.begin(ssid, password);   //***********on lance la connexion Wifi
  Serial.println();
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.write('.');          //************on attend la connexion en affichant des ......
  }
  Serial.println();

  serveur.begin();           //************* on démarre le serveur
  printHTTPServerInfo();    //*************on affiche les caractéristiques
}
//**************************************************LOOP*******************************************************************************
void loop() {
  testRequeteWeb();         //*************Lance la routine d'attente de client
}
Merci Yordi pour cette aide. Depuis un mois que j'apprends le HTML, je découvre chaque jour combien grande est mon ignorance!
Pour revenir à mon problème, je ne comprends pas:
dans ma déclaration CSS pour la class button, je n'ai pas mis de background-color; alors je ne devrais pas avoir de conflit ?
J'ai tout de même essayé de mettre !important dans mon style inline, mais cela n'a rien changé. Je crois que le défaut est ailleurs.
Cordialement
Michel
Modérateur
tu as une accolade en trop

  .button:hover {background-color: green;}
  .button:active {background-color: black;}
  } /* <=== ici */


corrige ceci, ensuite , retire les style inline et utilise tes ex1 et ex2 class pour les bg sans cibler uniquement les <p> Smiley cligne

class="button ex1" et .ex1{/*styles*/} au lieu de class="button" et p.ex1{/*styles*/}

dt
Modifié par gcyrillus (16 Mar 2020 - 21:32)
Merci gcyrillus pour ces conseils
L'accolade } a été mise par inadvertance au cours de mes multiples essais infructueux.
Je l'ai bien supprimée mais cela n'a rien changé.
J'ai créé les classes ex1 et ex2 uniquement pour afficher deux pavés de couleur.
Pour pouvoir changer le background de mes boutons de façon dynamique, je suis bien obligé de mettre le style inline alors que si je les figepar ex1?
Désolé de ces questions de débutant peut-être simplistes.
Michel
Modérateur
en fait les class sont préférable aux style en ligne, car elles sont facilement modifiable et ne pose pas de soucis de gestion de poids de sélecteur , comme Jordi te l'as indiqué.

tu lances ta fonction Arduino via click + javascript/ajax , tu peut intégrer au même moment un passage d'une classe à l'autre.

je te met ici un exemple , (dans la fonction js action(num,el)) https://codepen.io/gc-nomade/pen/NWqzKrJ



Après il vaut mieux faire ce retour à partir du statut de ton script arduino en utilisant des noms de class comme ouvert/fermer, qui ont un sens et réutilisables sur d'autre projets sans les pollués en n'ayant que les styles à toucher pour le visuel.
Modifié par gcyrillus (17 Mar 2020 - 12:33)
Meilleure solution
Il y a une chose qui est clair, malgré tout ce que j'ai pu apprendre depuis un mois sur HTML,CSS, JAVASCRIPT,
tout ce que j'ai pu lire ça et là sur le Web,
j'aurai été incapable de trouver cette solution. Je vous remercie énormément car je commençais à déprimer et ce n'est pas bon pour un septuagénaire!
Juste deux dernières questions si ce n'est pas abuser:
que signifie ~ devant className et pourquoi y a-t'il des espaces autour de ex1 ex2 ?
Merci encore
Michel