Bonsoir,

Sans solution à apporter, je proposerais d'effectuer une connexion à la base de donnée seulement si il y a bien une adresse mail valide passée en $_POST.

Pour éviter de soumettre à nouveau ton formulaire sur un refresh de ta page , un header('location: pageDuFormulaire.php'); au moins dans le cas où l'adresse mail est validée et enregistrée.

Dans quelles circonstances est ce que cela bugue ? uniquement avec une adresse mail valide ou n'importe qu'elle adresse ?

Si tu n'est pas certain de ta regex, tu peut faire quelques test avec https://www.php.net/manual/fr/filter.examples.validation.php pour éliminer un éventuelle problème de connexion ou d’écriture en base de donnée.

Il y aura surement d'autre réponses Smiley smile

Cdt
Voilà, mon objectif me semblait très simple mais je me retrouve avec pas mal de problèmes
Je souhaite que les utilisateurs qui veulent recevoir un email de news puissent s'inscrire en saisissant un email dans un champ.
Une fois saisit, l'utilisateur clic sur le bouton SUBSCRIBE pour qu'ensuite son adresse email soit inscrite dans un tableau. Le tableau ayant 2 colonnes, l'une ID auto incrémenté et la seconde, l'adresse email.
J'ai le code suivant dans ma page PHP

<?php
$servername = "mysql.XXX.com";
$database = "newsletter";
$username = "username";
$password = "mdp";
$conn = mysqli_connect($servername, $username, $password, $database);
if(isset($_POST['subscribe'])){
     if(empty($_POST['email_newsletter'])){
          echo '<script>alert("empty field!")</script>';
     }else{
          if(!preg_match("#^[a-z0-9_-]+((\.[a-z0-9_-]+){1,})?@[a-z0-9_-]+((\.[a-z0-9_-]+){1,})?\.[a-z]{2,}$#i",$_POST['email_newsletter'])){
               echo '<script>alert("incorrect email address!")</script>';
         }else{
               $req = $sql->prepare('INSERT INTO newsletter(email) VALUES(:email_newsletter)');
               $req->execute([':email_newsletter' => $_POST['email_newsletter']]);
          }
     }
}
mysqli_close($conn);
?>
<form style="" method="post" action="">
<input name="email_newsletter" type="email" value="<?php if(isset($_POST['email_newsletter'])){echo $_POST['email_newsletter'];} ?>"/>
<button name="subscribe" type="submit">SUBSCRIBE!</button>
</form>


La connexion se fait bien mais l'insertion ne se fait pas dans le tableau. Et pire, le <form> étant dans mon <footer>, ce dernier disparait complètement une fois l’actualisation de la page faite après que l’utilisateur ai cliqué sur SUBSCRIBE.
De plus, si je souhaite F5 ou ctrl+F5, j'ai le message suivant:
a écrit :
Pour afficher cette page, les informations précédemment transmises par Firefox doivent être renvoyées. Ceci répétera toute action (telle qu’une recherche ou un ordre d’achat) entreprise précédemment.

Et que je fasse "Renvoyer" ou "Annuler", mon <footer> a toujours disparu.
Étant totalement noob, je n'ai aucune piste de solution :X.

Merci très grandement par avance de votre temps.
Modifié par westman (26 Jul 2024 - 21:40)
Bonjour,

Avant tout il ne faut pas confondre "réactif" et "responsive", a priori si je pars de ce que vous décrivez vous évoquez plutôt le responsive design.

Alors la première chose à savoir c'est qu'il faut coder en mobile first. Je vous laisse rechercher ce que signifie ces mots clés de manière fine mais, pour l'instant, disons qu'il s'agit de coder en priorité pour les téléphones mobiles et ensuite de surcharger les règles CSS pour les ordinateurs de bureau.

Les points de rupture, c'est la structure du site web qui les détermines, pas les devices des appareils des utilisateurs*** : premièrement il y aurait beaucoup trop de modèles à prendre en compte, ensuite c'est bien plus logique de régler les points de rupture par rapport à la structure du site.

Pour ce faire vous avez dû entendre parler des Media Queries. Ça, c'était à l'époque de grand papa, maintenant on a les Container Queries. Mais avec les systèmes de grilles actuels (grid et flex) il y a beaucoup de cas de figure où vous pouvez même carrément vous en passer.

Flexbox vs grid : le premier a tendance à se structurer par rapport à son contenu, le deuxième par rapport au template du site. Par exemple, pour la structure d'un site web, grid layout est à préférer. En plus ça sera plus performant.

Pour auditer le front de votre site commencez par utiliser un des outils les plus importants disponible gratuitement dans la console d'inspection de votre navigateur Chrome : Lighthouse. Ça vous donnera des informations sur la structure front de votre code, sur les performances, sur le localStorage, sur l'accessibilité, etc ; avec des conseils pratiques et éventuellement des ressources à lire pour comprendre le pourquoi du comment (par exemple, pour les images, utiliser les attributs srcset et compression WEBP ou AVIF plutôt que du JPEG).

L'accessibilité est un monde en soit, difficile à retranscrire ici. Disons-le clairement : entre les préconisations théoriques et le concret de ce que peuvent faire les lecteurs d'écrans il peut y avoir un monde et pour le développeur c'est le foutoir complet (un peu moins dernièrement). On a parfois l'impression d'être un voyant qui doit retranscrire en braille un livre a destination de non voyants (pour ne citer qu'eux) avec pour outils un vieux dictionnaire braille incomplet et pas à jour qui donnera des certitudes qui au final se révèleront fausses, mais on ne s'en apercevrait que très tard car on a du mal à avoir un retour sur ce que l'on produit à ce niveau. C'est incroyable le nombre de croyances à fausses que l'on trouve sur le web à ce sujet. Commencez par utilisez la bonne sémantique pour votre code HTML, une sémantique appropriée et valide, ensuite seulement vous vous pencherez sur les spécifications ARIA.

J'ai survolé toutes les questions - elles étaient un peu nombreuses pour un seul post - pour en venir au plus important maintenant : quoi que vous fassiez codez en composants. Que vous utilisiez des frameworks, qui de toute façon utilisent le plus souvent ce concept, ou que vous codiez vos styles et vos scripts de manière monolithique, ne perdez jamais de vue que vous serez toujours gagnant à décomposer votre code en composants.

Je donne un exemple : j'ai besoin d'un slideshow (ou d'un accordéon, ou d'une série d'onglets, etc) sur une des pages de mon site et pour cela je vais créer des styles et des scripts. Très bien, mais je ne vais pas réfléchir à la manière dont je vais l'intégrer seulement pour cette unique page, mais potentiellement pour toutes les pages web de mon site, et même plusieurs fois sur une page. Du coup tout le code développé va s'en ressentir (je ne vais pas cibler une unique ID dans une page mais plutôt une classe CSS générique que je récupérerai dans un tableau JavaScript, etc). C'est sans doute le conseil le plus précieux que de mon côté je pourrais vous donner. Les points évoqués plus haut vous les trouverez aisément en ligne, mais cette histoire de composants il ne faut pas passer à côté.

___
*** Ça c'est pour la beauté de la théorie mais dans la pratique ce n'est pas toujours vrai : à la sortie du premier iPhone les dev's de Facebook avaient plié leur site web en quatre pour le rendre compatible avec le device du iPhone de première génération. Hors de question d'imaginer que le site ne soit pas optimisé pour le téléphone le plus hype du moment.

Modifié par Olivier C (25 Jul 2024 - 22:16)
Bonjour,

Je travaille sur un projet qui implique la création d'un site Web réactif et je contacte cette communauté pour obtenir des conseils et des bonnes pratiques.

Spécifiquement; Je m'efforce de garantir que le site Web offre une expérience utilisateur optimale sur différents appareils ; des ordinateurs de bureau aux smartphones. Bien que j'aie fait quelques recherches et mis en œuvre plusieurs techniques telles que les requêtes multimédias et les dispositions de grille flexibles ; Je cherche à affiner mon approche et à en apprendre davantage sur les stratégies avancées.

Comment déterminer les meilleurs points d’arrêt pour différents appareils ? Existe-t-il des outils ou des méthodes que vous utilisez pour tester et optimiser efficacement ces points d'arrêt ?

Flexbox vs Grid Layout : dans quels scénarios préférez-vous utiliser Flexbox plutôt que CSS Grid ? ou vice versa? Je suis curieux de savoir comment ces modèles de mise en page fonctionnent dans les conceptions réactives et de connaître les conseils pratiques que vous pourriez avoir pour les exploiter.

Quelles sont vos techniques de prédilection pour garantir qu'un site réactif se charge rapidement sur tous les appareils ? Des recommandations pour optimiser les images ou minimiser CSS/JavaScript pour améliorer les performances ?

Suivez-vous des pratiques spécifiques pour vous assurer que les conceptions réactives sont également accessibles aux utilisateurs handicapés ?

Merci d'avance pour votre aide et votre assistance.
Modifié par besossenorita (25 Jul 2024 - 08:27)
upload/1721853446-78493-sans-titre-2.gif salut et merci de te pencher sur mon probleme
j'ai fait ceci
  <input type="radio" name="select" id="img-tab-2" >
  <label for="img-tab-2" style="background-image: url(https://images.unsplash.com/photo-1558981359-219d6364c9c8?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60);"></label>
  <img src="https://images.unsplash.com/photo-1558981359-219d6364c9c8?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60" border="0" class="petiteimage" >

ça donne ça
merci
bonjour a tous j'ai trouve sur le web une galerie d'images sympa que j essaye de customiser
il y a une partie haute qui est une zone d'affichage large,
une zone de thumbnails dont l'opacité serait a 0.5 , au clic l'image background s'affiche dans la partie haute
au survol du thumbnail je souhaite que l'opacité du thumbnail soit augmentée

ma question est comment faire pour que les thumbnails aient leur opacité à 0.5
comment instauré cet effet hover sur les thumbnails pour augmentée leur opacité au survol?
j'ai réussi via le developper et j'ai une image pour montrer ce que ca donnerait
<!DOCTYPE html>
<html lang="fr"> 
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <link href="https://fonts.googleapis.com/css?family=Josefin+Sans:300,400,400i|Nunito:300,300i" rel="stylesheet">
        <link rel="stylesheet" href="css/style.css">
        <link rel="shortcut icon" type="image/png" href="img/favicon.png">
        <title>CSS Grids Gallery</title>
    </head><body><div class="fond_ecran"><div class="milieu"><h1>Jérémie Parmentier</h1><h2>photographie</h2>
	<div class="gallery">
  <input type="radio" checked="checked" name="select" id="img-tab-1">
  <label for="img-tab-1" style="background-image: url(https://images.unsplash.com/photo-1558980664-769d59546b3d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjExMDk?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjExMDk0fQ&auto=format&fit=crop&w=800&q=60);"></label></label>
  <img src="https://images.unsplash.com/photo-1558981000-f294a6ed32b2?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjc5NjV9&auto=format&fit=crop&w=2550&q=80" border="0">

  <input type="radio" name="select" id="img-tab-2">
  <label for="img-tab-2" style="background-image: url(https://images.unsplash.com/photo-1558981359-219d6364c9c8?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60);"></label>
  <img src="https://images.unsplash.com/photo-1558981359-219d6364c9c8?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60" border="0">

  <input type="radio" name="select" id="img-tab-3">
  <label for="img-tab-3" style="background-image: url(https://images.unsplash.com/photo-1558981285-501cd9af9426?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60);"></label>
  <img src="https://images.unsplash.com/photo-1558981285-501cd9af9426?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60"border="0">
  
  <input type="radio" name="select" id="img-tab-4">
  <label for="img-tab-4" style="background-image: url(https://images.unsplash.com/photo-1558981001-1995369a39cd?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60);"></label>
  <img src="https://images.unsplash.com/photo-1558981001-1995369a39cd?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60"border="0">
  
  <input type="radio" name="select" id="img-tab-5">
  <label for="img-tab-5" style="background-image: url(https://images.unsplash.com/photo-1558980394-dbb977039a2e?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60);"></label>
  <img src="https://images.unsplash.com/photo-1558980394-dbb977039a2e?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60"border="0">
  
  <input type="radio" name="select" id="img-tab-6">
  <label for="img-tab-6" style="background-image: url(https://images.unsplash.com/photo-1558980664-769d59546b3d?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60);"></label>
  <img src="https://images.unsplash.com/photo-1558981000-f294a6ed32b2?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjc5NjV9&auto=format&fit=crop&w=800&q=60"border="0">

  <input type="radio" name="select" id="img-tab-7">
  <label for="img-tab-7" style="background-image: url(https://images.unsplash.com/photo-1558981403-c5f9899a28bc?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60);"></label>
  <img src="https://images.unsplash.com/photo-1558981403-c5f9899a28bc?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=601.2.1&auto=format&fit=crop&w=800&q=60"border="0">
  
  <input type="radio" name="select" id="img-tab-8">
  <label for="img-tab-8" style="background-image: url(https://images.unsplash.com/photo-1558980664-2506fca6bfc2?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60);"></label>
  <img src="https://images.unsplash.com/photo-1558980664-2506fca6bfc2?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60"border="0">
</div>
</div>
</div>
    </body>
</html>
body{
	background-color: #808080;
}

.fond_ecran 
{  height: 600px;
  width: 800px;
  margin: auto;
  border: 0px solid #4287f5;
    background-image: url("../img/fd_ecran2.jpg");
}
.gallery__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.milieu 
{  height: 600px;
padding-top:100px;
  width: 600px;
  margin: auto;
  border: 0px solid #4287f5;
    text-align: center;
}
h1{Font-family: Dejavu Sans, Arial, Verdana, sans-serif;}

.gallery {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-gap: 20px;
  grid-column-start: 1;
  grid-row-start: 1;
  grid-row-end: 3;
  align-content: start;
  max-width: 700px;
  margin: 0 auto;
  transition: all 150ms linear;
}

.gallery input[type="radio"] {
  display: none;
}

.gallery label {
  position: relative;
  display: block;
  padding-bottom: 60%;
  margin: 5px;
  cursor: pointer;
  background-repeat: no-repeat;
  background-size: cover;
  background-position: 50% 50%;
}

.gallery label:before {
  border: 1px solid #e3e3e3;
  content: '';
  position: absolute;
  left: -5px;
  right: -5px;
  bottom: -5px;
  top: -5px;
}

.gallery img {
  display: none;
  grid-column-start: 1;
  grid-column-end: 5;
  grid-row-start: 1;
  grid-row-end: 2;
  width: 100%;
  transition: all 150ms linear;
}

.gallery input[name="select"]:checked + label + img {
  display: block;
}

.gallery input[name="select"]:checked + label:before {
  border: 1px solid #000;
}



merci de m'aider pour la partie css et le comportement :hover des thumbnails, ainsi que pour l'affectation de l opacité des thumbnails,
bien cordialement,

upload/1721850479-78493-sans-titre-1.gif
QuentinC a écrit :
Bonjour,


Je ne suis pas sûr de bien comprendre la question, mais
1 - La disposition visuelle n'a généralement aucune influence sur ce qui est lu ou non par les lecteurs d'écran, à quelques exceptions près.
2 - Par contre display:none masque le contenu pour tout le monde, y compris les lecteurs d'écran; c'est une des rares propriétés CSS qui ont une influence
3 - IL n'est pas garanti que les attributs ARIA sur des éléments non focusables, non landmarks, ou avec un rôle habituellement attribué à de tels éléments, soient bien lus.
Donc oui il faut que l'élément qui porte le aria-expanded soit focusable, et c'est lui qui déclenche l'action de dépli/repli.
De toute façon si l'élément qui déclenche l'action n'est pas focusable, alors il n'est pas accessible aux utilisateurs exclusivement au clavier.


Dis-moi si ça répond à la question ou si c'est à côté de la plaque...

@quentinC
Oui cela répond tout à fait , je comprend que les attribut role sont inutiles, voir source de confusion, dans ce cas précis puisqu'il ne s'agit que de cosmétique sans conséquences.

Merci beaucoup Smiley smile
Bonjour,

a écrit :
L'affichage en grille (grid) et des éléments focusable via tabindex semblerait être "une alternative accessible" pour un système visuel de boite à onglets bien que plusieurs éléments se superposent dans la même zone d'affichage. Est ce un risque ou bien la feuille de style (sans display:none;) n'a pas d'incidences ?


Je ne suis pas sûr de bien comprendre la question, mais
1 - La disposition visuelle n'a généralement aucune influence sur ce qui est lu ou non par les lecteurs d'écran, à quelques exceptions près.
2 - Par contre display:none masque le contenu pour tout le monde, y compris les lecteurs d'écran; c'est une des rares propriétés CSS qui ont une influence
3 - IL n'est pas garanti que les attributs ARIA sur des éléments non focusables, non landmarks, ou avec un rôle habituellement attribué à de tels éléments, soient bien lus.
Donc oui il faut que l'élément qui porte le aria-expanded soit focusable, et c'est lui qui déclenche l'action de dépli/repli.
De toute façon si l'élément qui déclenche l'action n'est pas focusable, alors il n'est pas accessible aux utilisateurs exclusivement au clavier.


Dis-moi si ça répond à la question ou si c'est à côté de la plaque...
Salut

Ton fichier s'appelle bien fruits.json ? et est-il au même niveau (dossier) que ton fichier javascript ?

Y'a t-il une erreur dans ta console ?

c'est ton
const fruits = await fetch("fruits.json").then(fruits => fruits.json());
    console.log(fruits);
    const affichage = fruits[0];
    console.log(affichage);

que tu essayes de tester et les consoles logs qui n'affiche rien ?
Modifié par JENCAL (23 Jul 2024 - 17:26)
@quentinC
a propos de https://forum.alsacreations.com/topic-1-91081-1.html#p581666

Merci de ton retour, j'en conclu, surement hâtivement, que ces attributs role ici sont une surcharge inutile si non complété avec aria-current et aria-expanded et une pointe de javascript .

L'affichage en grille (grid) et des éléments focusable via tabindex semblerait être "une alternative accessible" pour un système visuel de boite à onglets bien que plusieurs éléments se superposent dans la même zone d'affichage. Est ce un risque ou bien la feuille de style (sans display:none;) n'a pas d'incidences ?

cdt
Bonjour,

Dans un code html, j'ai un lien mais même avec le css, ça marche pas.

Voilà l'original :
<a href="?page=contact" ...


Et voici ce que j'ai mis :
<a href="?page=contact" onmouseover="this.style.background='yellow';this.style.color='#000';"


Bon, ça fonctionne bien quand la souris passe sur le lien, mais le lien rest coloré si la souris va ailleurs.

Pourriez-vous m'aider pout enlever ce BG lorsque le lien n'"est plus ciblé ?

Merci de votre aide.

QI98
Modifié par qi98 (23 Jul 2024 - 14:01)
a écrit :
J'y ai ajouté des attributs role, mais je ne suis pas certains qu'il soient tous utiles car pas de display:none ni de js impliqués, les balises dt et dd sont dans le flux et dans leur usage habituel. @quentinC saura dire et taper sur les doigts du mauvais élève


Ton utilisation de tablist est effectivement étrange.
1. Normalement, on a la liste des onglets à la suite, et le contenu affiché selon l'onglet en cours est ailleurs, pas intercalé à l'intérieur de la liste
2. Normalement, un seul onglet ne peut être ouvert à la fois. Activer un onglet affiche le contenu correspondant et masque le contenu de l'onglet précédemment actif.

Si tu n'es pas dans ce cas de figure, c'est plutôt un pattern de details/summary, ou avec ARIA, aria-expanded, qu'il faut utiliser.

Petit bonus pour les onglets: indiquer l'onglet actuellement actif avec aria-current.

Cela dit, Jaws et NVDA retranscrivent bien les bonnes informations.
@niuxe oups oui bien sur !!

Du coup voila ma contrib en js en mirroir au php précédent, du coup avec fetch() sur window.onload() pour marquer une difference ...

<!DOCTYPE html>
<html lang="fr">	
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" />
		<title>Fruits rouges</title>
		<style>
			nav {
			  display:flex;
			  gap:1em;
			  justify-content:center;
			}
			body {
			  display: grid;
			  min-height: 100vh;
			  margin: 0;
			  grid-template-rows: auto 1fr auto;
			  text-align: center;
			  background: #ACD5A0
			}
			main {
			  width:100%;
			  max-width: 800px;
			  min-height: 100%;
			  margin: auto;
			}
			  section {
			  display: grid;
			  gap: 1em;
			  text-align: initial;
			}
			  header,footer{
			  background:#345;color:white;=
			}
			  main {
			  background:tomato;
			  padding:1em;
			}

			a{
			  padding:1em;
			}
			.active{
			  background: white
			}
			
		</style>
	</head>
	<body>
		<header><h1>Les fruits rouges</h1></header>
		<main>
			<nav>
				
			</nav>			
			<section>
				<h2></h2>
				<div></div>
			</section>
		</main>
		<footer><p>Hmm des fruits rouges</p></footer>
	</body>
	
		<script>
window.onload=function() {
    fetch("fruits.json").then(response => response.json()).then(fruits => {
		// on attrape la valeur fruit de L'URL si il y a
		const params = new Proxy(new URLSearchParams(window.location.search), {
			get: (searchParams, prop) => searchParams.get(prop),
		});
		let value = params.fruit;
		// traitement du json
		let title = fruits[0]["titre"];
		let content = fruits[0]["description"];
		let nav = ``;
		let active='';
		let lefruit= title;
		if(value==null) value= lefruit;
		// navigation + class active
		for (var i = 0; i < fruits.length; i++) {
			lefruit = fruits[i]["titre"];
			if (lefruit==value) active= 'active';
			else active="";
			nav += `<a href="?fruit=${lefruit}" class="${active}">${lefruit}</a>`;
		}
		
		for (let f =0; f< fruits.length;f++) {
			if(fruits[f]['titre']==value ) {
				title= fruits[f]['titre'];
				content = fruits[f]['description'];
				break; // on dés qu'on trouve
			}
		}
		// mise à jour des contenus
		document.querySelector("title").innerHTML = 'Fruits rouges '+title;
		document.querySelector("nav").innerHTML = nav;
		document.querySelector("h2").innerHTML = title;
		document.querySelector("div").innerHTML = content;
	})
	.catch(function () {
		// mise à jour des contenus
		document.querySelector("title").innerHTML = 'Pas de données disponibles';
		document.querySelector("nav").innerHTML = 'inconnue en base de données';
		document.querySelector("h2").innerHTML = 'Pas de données disponibles';
		document.querySelector("div").innerHTML = 'Aucune description disponible'; 
		
	});
};
		</script>
</html>

Si le fichier n'est pas trouvé ou invalide, la page indique une bdd sans données disponibles
Modifié par gcyrillus (22 Jul 2024 - 15:11)
@gcyrillus : Tu n'es pas du tout obligé de passer par du php pour faire ce genre de chose. En JS, tu peux gérer un GET (window.location.search & l'objet URLSearchParams). Je pense que tu le sais. Mais tu n'y as pas pensé Smiley smile

@ricem:
Lancement d'un serveur en local sur le port 3000

[ edit ]

edit en python

python3 -m http.server 3000


edit en php:

php -S localhost:3000


edit en express (nodeJS) Suivant la précédente technique. Sinon, avec express, on peut faire un peu plus simple

import express from 'express'
import fs from 'node:fs'
import path from 'path'
import { fileURLToPath } from 'url'

const app = express()
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

app.get('/', (req, res) =>{
    res.sendFile(path.join(__dirname, '/index.html'))
})

app.get('/app.js', function(req, res){
  res.sendfile(path.join(__dirname + '/app.js'));
});

app.get('/data.json', function(req, res){
  res.sendfile(path.join(__dirname + '/data.json'))
});


const port = 3000
app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})



[/ edit ]

data.json

[
    {
        "theme": "cerise",
        "titre": "Cerise",
        "description": "La cerise est le fruit comestible du cerisier, il s'agit d'un fruit charnu à noyau de forme sphérique, généralement de couleur rouge."
         
    },
 
    {
        "theme": "fraise",
        "titre": "Fraise",
        "description": "La fraise est un petit fruit rouge issu des fraisiers, espèces de plantes herbacées appartenant au genre Fragaria"
    },
 
    {
        "theme": "framboise",
        "titre": "Framboise",
        "description": "La framboise est un fruit rouge issu du framboisier, un arbrisseau de la famille des rosacées.."
         
    },
 
    {
        "theme": "mure",
        "titre": "Mûre",
        "description": "La mûre est un fruit comestible de la ronce commune, buisson épineux très envahissant du genre Rubus, de la famille des Rosacées, comme le framboisier"
    }
]


index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <ul>
        <li><a href="?theme=cerise">Cerise</a></li>
        <li><a href="?theme=fraise">Fraise</a></li>
        <li><a href="?theme=framboise">Framboise</a></li>
        <li><a href="?theme=mure">Mure</a></li>
    </ul>
    <div id="result"></div>
    <script src="app.js"></script>
</body>
</html>


app.js

(()=>{
    let getData = async ()=>{
        let response = await fetch('http://localhost:3000/data.json')
        return await response.json()
    }
    if(window.location.search.trim() !== ""){
        let querystring = window.location.search,
            params = new URLSearchParams(querystring),
            theme = params.get('theme'),
            row = {}
        getData().then(d =>{
            let row = d.find(e => e.theme === theme)
            document.getElementById('result').innerHTML = `
                <h1>${row.titre}</h1>
                <div>${row.description}</div>
            `
        })
    }
})()

Modifié par niuxe (22 Jul 2024 - 14:26)
rebonsoir,

Pour l'appel des pages avec get, c'est à faire dans un fichier php en verifiant si il y a une requete $_GET et choisir l'une ou l'autre des infos de fruits stocké dans ton json.

En gros cela donnerait quelque chose comme ceci :
<?php
	// chargement du json
	$fruits= json_decode(file_get_contents('fruits.json'), true);
	// premier enregistrement à montrer par défaut
		$title= $fruits[0]['titre'];
		$content = $fruits[0]['description'];	
		
	// y a t-il une requete pertinente ?
	if(isset($_GET['fruit'])) {	
                                // si l'on ne trouve rien
				$title= 'Ce fruit est absent de la base de donnée';
				$content = 'Il n\'y a aucune description à afficher';
		// maintenant on cherche
		foreach ($fruits as $subKey => $subArray) {
			if( $subArray['titre'] == trim($_GET['fruit'])) {
				$title=$subArray['titre'];
				$content = $subArray['description'];
				break;// on s'arrete des qu'on trouve
			} 
		}
	}
?><!DOCTYPE html>
<html lang="fr">	
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" />
		<title>Fruits rouges - <?= $title ?></title>
		<style>
			nav {display:flex;gap:1em;}
		</style>
	</head>
	<body>
		<h1>Les fruits rouges</h1>
		<main>
			<nav>
				<?php
				// affichage des liens vers les données trouvées
					$i = 0;
					while ($i < count($fruits)) {
						$fruit=$fruits[$i]['titre'];
						echo '<a href="?fruit='.$fruit.'">'.$fruit.'</a>';
						$i++;
					}
				?>		
			</nav>			
			<section>
				<h2><?= $title ?></h2>
				<?= $content ?>
			</section>
		</main>
		<footer><p>Hmm des fruits rouges</p></footer>
	</body>
</html>

partant de ton fichier fruit.json
[
    {
        "titre": "Cerise",
        "description": "La cerise est le fruit comestible du cerisier, il s'agit d'un fruit charnu à noyau de forme sphérique, généralement de couleur rouge."
         
    },
 
    {
        "titre": "Fraise",
        "description": "La fraise est un petit fruit rouge issu des fraisiers, espèces de plantes herbacées appartenant au genre Fragaria"
    },
 
    {
        "titre": "Framboise",
        "description": "La framboise est un fruit rouge issu du framboisier, un arbrisseau de la famille des rosacées.."
         
    },
 
    {
        "titre": "Mûre",
        "description": "La mûre est un fruit comestible de la ronce commune, buisson épineux très envahissant du genre Rubus, de la famille des Rosacées, comme le framboisier"
    }
]

Ta page affiche le premier fruit par défaut.
Si la requête correspond à l'un des fruits stocké, il sera affiché en lieu et place dans la page, sinon qu'il n'est pas dans la bdd.
Modifié par gcyrillus (21 Jul 2024 - 23:39)
QuentinC a écrit :


const fruits = await fetch("fruits.json").then(fruits =&gt; fruits.json());


J'éviterais de mélanger le code async/await et le code style promise. C'est source de confusion. Choisis soit l'un, soit l'autre, mais pas les deux en même temps.

A noter que pour que await fonctionne, il faut que ta fonction soit déclarée async. Sinon, c'est une erreur de syntaxe.


Le souci c'est que je viens de débuter en API et que je n'ai rien trouvé comme tuto explicatif pour m'apprendre.
et sinon le code JS en lui-même hormis le "innerText" qu'il va falloir que je remplace ?
et comment je le lie (lier) au "href du fichier html pour qu'il puisse s'afficher ?
Merci.
Bonsoir gcyrillus, très joli le résultat, c'est dommage que je ne m'y connaisse pas trop en "grid" hormis quelque notion de mise en page pour passer de 3 à 2 et une colonne en "media queries", je mettais arrêté un peu plus sur le "flexbox"...

niuxe, j'ai compris un peu le principe de ton code ça fonctionne un peu comme les ancres sur un espace plus restreint du coups il ne peut pas afficher les 3 div...on va dire que c'est un peu du bidouillage Smiley confused mais ça fonctionne.

parcontre, j'aimerais un peu plus de précision sur la 3éme technique "l'appel des pages"..merci.
Modifié par ricem (21 Jul 2024 - 22:13)
Bonsoir,

Après une très rapide lecture de 30 secondes, IL y a plusieurs choses qui me chaffouinent dans ton code:

const fruits = await fetch("fruits.json").then(fruits => fruits.json());


J'éviterais de mélanger le code async/await et le code style promise. C'est source de confusion. Choisis soit l'un, soit l'autre, mais pas les deux en même temps.

A noter que pour que await fonctionne, il faut que ta fonction soit déclarée async. Sinon, c'est une erreur de syntaxe.

a écrit :
articleElement.innerText = affichage.description;


Si ta description contient du code HTML, c'est innerHTML qu'il faut utiliser.
Bonsoir,

Personnellement , j'ai penser de suite à une liste de définition. et à grid qui permet facilement de faire des boites à onglet sans positionement et à coup de tabindex Smiley smile J'y ai ajouté des attributs role, mais je ne suis pas certains qu'il soient tous utiles car pas de display:none ni de js impliqués, les balises dt et dd sont dans le flux et dans leur usage habituel. @quentinC saura dire et taper sur les doigts du mauvais élève Smiley cligne

En raccourcie, voici l'idée: https://codepen.io/gc-nomade/pen/zYVqQRK
Modifié par gcyrillus (21 Jul 2024 - 21:34)
Re, du coup j'ai essayé en créant une API mais rien ne fonctionne (d'ailleurs, j'ai créé un nouveau sujet => https://forum.alsacreations.com/topic-5-91082-1-Afficher-la-reponse-json.html)
sinon, en quoi consiste la 3éme solution, j'ai pas trop compris aurais tu un exemple ?
merci.

Edit : Je ne connaissais pas ces techniques ni ces éléments...ça peut être intéressant je vais approfondir (me renseigner) Double merci.
Modifié par ricem (21 Jul 2024 - 19:11)
Bonjour,

Je test un code api, sauf que rien ne fonctionne comme il le faut... Smiley ohwell

rien ne s'affiche, je fais un console log pour vérifier si le fetch fonctionne...même ça je n'y arrive pas Smiley decu
je vous mets mes codes :
!DOCTYPE html>
<html lang="fr">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="fruits.css">
    <script src="fruits.js" defer></script>
    <title>Fruits rouges</title>
</head>
 
<body>
    <h1>Les fruits rouges :</h1>
    <main>
        <section class="liste">
            <ul>
                <ul>
                    <li><a href="">Cerise</a></li>
                    <li><a href="">Fraise</a></li>
                    <li><a href="">Framboise</a></li>
                    <li> <a href="">Mûre</a></li>
                </ul>
            </ul>
        </section>
 
        <section class="contenu">
 
        </section>
    </main>
 
</body>
 
</html>


[
    {
        "titre": "Cerise",
        "description": "La cerise est le fruit comestible du cerisier, il s'agit d'un fruit charnu à noyau de forme sphérique, généralement de couleur rouge."
         
    },
 
    {
        "titre": "Fraise",
        "description": "La fraise est un petit fruit rouge issu des fraisiers, espèces de plantes herbacées appartenant au genre Fragaria"
    },
 
    {
        "titre": "Framboise",
        "description": "La framboise est un fruit rouge issu du framboisier, un arbrisseau de la famille des rosacées.."
         
    },
 
    {
        "titre": "Mûre",
        "description": "La mûre est un fruit comestible de la ronce commune, buisson épineux très envahissant du genre Rubus, de la famille des Rosacées, comme le framboisier"
    }
]


/ // Récupération des fruits depuis le fichier JSON
const fruits = await fetch("fruits.json").then(fruits => fruits.json());
    console.log(fruits);
    const affichage = fruits[0];
    console.log(affichage);
 
 
// Fonction qui génère toute la page web
function genererFruits(fruits) {
    for (let i = 0; i < fruits.length; i++) {
        // On créer une balise h2 pour le titre
        const titreElement = document.createElement("h2");
        titreElement.innerText = affichage.titre;
 
        // On créer une balise article pour la description
        const articleElement = document.createElement("article");
        articleElement.innerText = affichage.description;
 
        // on selectionne la balise dans le code html
        const contenu = document.querySelector(".contenu");
 
        // On rattache les éléments au fichier html
        contenu.appendChild(titreElement);
        contenu.appendChild(articleElement);
    }


merci.
QuentinC a écrit :


Sinon troisième solution, tu le fais à l'ancienne, et tu gères la description à afficher avec par exemple un paramètre GET, p.ex. mapage.php?fruit=ffraise, mapage.php?fruit=framboise, etc.
L'avantage est que c'est très très simple, que tu n'as pas besoin de JavaScript, et que c'est beaucoup plus simple pour indexer ton contenu par les moteurs de recherche.


tu n'es pas obligé de passer par une querystring dans ce cas. Autant appeler une page : fraise.html ou cerise.html ou etc.

@ricem :

ton code html n'est pas valide. Tu ne peux pas avoir un élément <a> en tant qu'enfant direct d'un <ul>

Ce code est faux :

<ul>
    <a href=""><li>item 1</li></a>
    <a href=""><li>item 2</li></a>
    <a href=""><li>item 3</li></a>
</ul>


Alors que ce code est juste :

<ul>
    <li><a href="">item 1</a></li>
    <li><a href="">item 2</a></li>
    <li><a href="">item 3</a></li>
</ul>


La question que je me pose est : J'ai compris ce que tu souhaites faire. Mais avec quelle technique/technologie veux-tu le faire (JS/PHP/Python/Ruby/etc.) ?


edit
En faisant simple, tu peux tout à fait imaginer ce genre de techniques :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <main>
        <aside>
            <nav>
                <ul>
                    <li><a href="#cerise">cerise</a></li>
                    <li><a href="#fraise">fraise</a></li>
                    <li><a href="#orange">orange</a></li>
                </ul>
            </nav>
        </aside>
        <section>
            <div id="cerise">cerise </div>
            <div id="fraise">fraise </div>
            <div id="orange">orange </div>
        </section>
    </main>
</body>
</html>



body{
    font-family: sans-serif;
    margin: 0;
    padding: 0;
}

main{
    max-width: 600px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: repeat(12, 1fr);
}

aside{
    grid-column: 1 / 4;
}

section{
    grid-column: 5 / 12;
    height: 200px;
    overflow: hidden; /* auto ? */
}

section div{
    height: 200px;
}


N'oublie pas qu'il y a :
- l'élément <dl> qui selon moi se prête à ce genre de situation
- l'élément <details> qui est une autre possibilité
Modifié par niuxe (21 Jul 2024 - 13:15)
Bonjour,

IL y a plusieurs familles de solutions possibles:

Soit tu inclus toutes les descriptions directement dans le code, et le clic sur un élément ne fait qu'afficher la description choisie et masquer les autres.
Typiquement, en jouant avec la valeur de CSS display en JavaScript.
L'avantage, c'est que c'est simple, mais c'est difficilement envisageable si tu as beaucoup d'éléments.

Soit le clic déclenche le chargement d'un fragment de page et va l'afficher dans la zone voulue.
Pour ça, il faut te renseigner sur XMLHttpRequest ou l'API fetch, et ensuite c'est de la manipulation du DOM.
C'est clairement la solution la plus compliquée...

Sinon troisième solution, tu le fais à l'ancienne, et tu gères la description à afficher avec par exemple un paramètre GET, p.ex. mapage.php?fruit=ffraise, mapage.php?fruit=framboise, etc.
L'avantage est que c'est très très simple, que tu n'as pas besoin de JavaScript, et que c'est beaucoup plus simple pour indexer ton contenu par les moteurs de recherche.


Par contre je pense que ce sujet devrait être déplacé dans débutant, car c'est une question de comment faire assez générale, et non pas vraiment une question de sémantique ou de langage HTML pointue.
Bonjour, le titre n'est pas très explicite Smiley murf

J'ai deux div (section), dans une div j'ai une liste a puce et sur le deuxième div vide, je voudrait que quand on clique sur cerise (par exemple) que dans le second div apparaisse un titre et une description comme ceci :
<h2>La cerise :</h2>
<p>La cerise est le fruit comestible du cerisier, il s'agit d'un fruit charnu à noyau de forme sphérique, généralement de couleur rouge.</p>

Puis quand je clique sur Fraise, le code s'efface et laisse place à celui de la fraise.
Comment je peux faire, merci.

PS: j'ai le code sur codepen https://codepen.io/ricem/pen/qBzZKRr
Modifié par ricem (21 Jul 2024 - 10:10)
Heu, c'est un peu trop complexe a comprendre...comme les exemples valent mieux que les longs discours, concrètement pour une présentation comme celle-ci faite en html :
<h2>La cerise :</h2>
<p>La cerise est le fruit comestible du cerisier.</p>
<p>Il s'agit d'un fruit charnu à noyau de forme sphérique, généralement de couleur rouge.</p>

Comment se présenterait le même code en json :
{
        "titre": "Cerise",
        "description": "La cerise est le fruit comestible du cerisier.
Il s'agit d'un fruit charnu à noyau de forme sphérique, généralement de couleur rouge."      
}

Merci.
Modifié par ricem (21 Jul 2024 - 09:43)
Bonsoir,

Ne fournis pas ton code ou tes messages d'erreur sous forme d'images.
Les utilisateurs de lecteur d'écran comme moi ne peuvent pas les lire (sauf à demander à une IA), et plus généralement, celui qui pourrait t'aider ne peut pas les copier, ce qui ne va pas inciter à t'aider.
Poste donc du texte ou du code pour une réponse plus précise.

De façon générale, tu peux écrire tout ce que tu veux dans des chaînes de caractères au format JSON, si tu connais les règles de base:

* IL faut obligatoirement échapper " et \ en \" et \\
* Sauf erreur tu n'es pas strictement obligé d'après le standard, mais c'est quand même conseillé d'utiliser \r \n \t \b \f pour être sûr que tous les parseurs acceptent (notamment les navigateurs)
* Les commentaires sont fortement déconseillés car pas officiellement supportés, et peu de parseurs les supportent effectivement
* Les caractères de certaines plages doivent être obligatoirement écrits sous leur form \uXXXX, p.ex. U+0000 à U+001F (rare en-dehors de \r\n\t\b\f) (Je ne comprends pas pourquoi le standard l'impose, à part pour éviter un NUL littéral)
* Il est conseillé d'écrire les émojis sous leur forme UTF-16 échappée \uDXXX\uDXXX, pour les parseurs qui ont du mal avec UTF-8. Par contre d'après mes observations, en général pour les caractères accentués ça marche sans que ce soit nécessaire, i.e. pas besoin d'écrire "é" en "\u00e9".

Avec toutes ces règles, JSON n'est pas hyper pratique à écrire à la main.
Il y a des formats plus pratiques pour ça, comme TOML ou YAML.
Trou de mémoire mes Amis Smiley confused
Je veux pour coloriser mes PHP à l'écran utiliser la méthode avec les JS que je possèdes, et utiliserait il y a 10 ans, je souhaite retrouver un code qui me permette de passer mon PHP
à ce format, (ça doit être simple mais j'ai un trou de mémoire) .
Je souhaites obtenir juste ceci !

&lt;?php 
header (&quot;Content-type: image/jpeg&quot;); 
$un_tableau = imagecreatefromjpeg(&quot;logos/tableau001.jpg&quot;); 
$nxtableau = imagesx($un_tableau);$nytableau = imagesy($un_tableau);
$Photo = imagecreatefromjpeg(&quot;logos/tableau_interrieur001.jpg&quot;);
$nxPhoto = imagesx($Photo);$nyPhoto = imagesy($Photo);
$placeX = 559;$placeY =220;
imagecopymerge($Photo, $un_tableau, $placeX, $placeY, 0, 0, $nxtableau, $nytableau, 100);
imagejpeg($Photo);
?&gt;

Ne riez pas ... à mon âge il y a des petits trous comme ça !
Ah oui j'oubliais bon Week-End !
QuentinC a écrit :
j'utilise relativement peu les réseaux sociaux, et en particulier je trouve totalement inutile les liens partager sur facebook/instagram/tiktok/etc. aux abords des articles car je ne les utilise jamais.

Cela dépend évidemment et du type de site et du nombre de suiveurs sur une page sociale.
gcyrillus a écrit :
Ces liens pourrait être géré comme des notes de bas de page/article .

C’est peut-être une idée. Je me dirige pour l’instant plutôt vers une gestion par base de données. Le non-inscrit ne verrait pas ce lien, car nous risquons fort de le perdre s’il quitte le site. L’inscrit pourrait voir ce lien, car cela pourrait lui donner l’idée de nous soutenir sur les réseaux sociaux.
Bonsoir,

a écrit :
Et du coup quand la personne ferme le modal, ça réactualise la page.
je ne sais pas si c'est conventionnelle, mais ça fonctionne ^^


Tu auras quand même l'avertissement du navigateur si tu rafraîchis la page avec F5 sans cliquer sur le bouton pour fermer la pop-up.
C'est donc un peu de la magouille, et ce n'est pas fiable à 100%.

Ce qui est dit dans le post de 2014 que tu as retrouvé est toujours valable.

Tiens d'ailleurs, étrange, ce lien est cassé, j'obtiens un message bizarre de Chrome comme quoi il est bloqué. J'ai dû copier-coller l'URL manuellement pour l'ouvrir.


ET au fait, évite les up, c'est mal vu, surtout après seulement 2 ou 3 jours.
La fréquentation des forums n'est plus ce qu'elle était il y a 10 ou 20 ans, et c'est assez général, pas seulement ici. Ton sujet ne va plus se perdre si rapidement.
C@scou a écrit :
Aaaaah miles mercis gcyrillus, une solution élégante et simple presque inespérée !
Complètement absente de la doc en Français ! Ce qui me fais réaliser que la version française n'est pas toujours complète. Smiley ohwell
En tout cas c'est très exactement ce que je cherchais alors encore un grand merci à toi. Question idiote, comment a tu pris connaissance de cette propriété ? Je veux dire c'est vraiment très obscur comme truc, un peu comme object-fit il y a quelques années (pour moi en tout cas Smiley cligne ).


Merci et de rien, c'est le pour quoi du Forum Smiley cligne
Dans mes bricoles, je me suis probablement trouvé comme toi dans les début de flex face à ce comportement à priori inattendu . D'abord en m'appuyant sur un simple margin:auto; pour m'affranchir du défaut puis ai cherché le comment du pourquoi sur la doc MDN en testant safe qui est maintenant bien compris.

Cdt
Aaaaah miles mercis gcyrillus, une solution élégante et simple presque inespérée !
Complètement absente de la doc en Français ! Ce qui me fais réaliser que la version française n'est pas toujours complète. Smiley ohwell
En tout cas c'est très exactement ce que je cherchais alors encore un grand merci à toi. Question idiote, comment a tu pris connaissance de cette propriété ? Je veux dire c'est vraiment très obscur comme truc, un peu comme object-fit il y a quelques années (pour moi en tout cas Smiley cligne ).
a écrit :
Par souci de transparence, nous indiquons alors le lien vers l’un de ces réseaux, mais la contrepartie est qu’il existe alors un fort risque de perdre le prospect qui ne nous connait pas encore.
Une solution pourrait être de ne pas afficher le lien pour les visiteurs non inscrits tandis que cela renforcera notre présence sociale pour les autres en voyant le lien. Qu’en penses-tu ?


Je ne suis pas dans le business des actualités, j'utilise relativement peu les réseaux sociaux, et en particulier je trouve totalement inutile les liens partager sur facebook/instagram/tiktok/etc. aux abords des articles car je ne les utilise jamais.

Donc là par contre je ne comprends absolument pas ton histoire de prospect, encore moins les enjeux qu'il y a derrière, et donc je ne vais donc pas pouvoir beaucoup t'aider.
Bonjour, QuentinC,
Voilà un point de vue pertinent et fort bien expliqué. Bravo et merci.
Le fond reste que si dans le cas général le comportement standard est attendu, il n’en reste pas moins que sur une page très particulière, une seule page en fait, nous écrivons un article d’actualité et de larges extraits sont publiés sur les réseaux sociaux.
Par souci de transparence, nous indiquons alors le lien vers l’un de ces réseaux, mais la contrepartie est qu’il existe alors un fort risque de perdre le prospect qui ne nous connait pas encore.
Une solution pourrait être de ne pas afficher le lien pour les visiteurs non inscrits tandis que cela renforcera notre présence sociale pour les autres en voyant le lien. Qu’en penses-tu ?
Une autre idée ?
Modifié par Pyanepsion (19 Jul 2024 - 07:46)
a écrit :
Est-ce que tu peux nous dire l'impact pour un lecteur d'écran, stp ? J'imagine que ça ne change rien, je veux juste être sur.


Si par impact tu veux dire par là est-ce qu'il y a une différence de rendu du lecteur d'écran entre la version avec ou sans <hgroup>, la réponse est non, ça ne change rien, ou alors quelque chose de négligeable.
50 Dernières réponses