11528 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

Comme dit dans le titre problème avec ces 2 paramètres que je ne comprends pas vu mon niveau en javascript.

Quand je clique sur 2 ou 3 cases à cocher puis sur le mot "Nom du service" pour trier, tout va bien.
Par contre si je clique sur le petit bouton bleu en haut à droite pour faire une sorte de reset du tableau et qu'ensuite je re-clique sur des cases puis que je trie. là çà bug.

Le code :
https://codepen.io/TurtleVape/pen/BaQjOaQ

Le code exécuté en cliquant sur le bouton bleu :
function vide() {
	var myBoxEven = new Event('input',{bubbles:true,cancelable: true});
	myBox.value="";
	myBox.dispatchEvent(myBoxEven);
	stylraz(1)
}


Comment résoudre ce problème ?
Cordialement
Jérôme
Modifié par Jerome87 (09 Feb 2021 - 01:34)
Modérateur
Et l'eau,

J'avoue ne pas avoir lu ton js. Tu as déjà un bug au niveau du trie.

- coche 2 checkbox (Accès du périphérique d'interface utilisateur, Acquisition d'image Windows (WIA))
- trie et tu verras que tes :checked n'ont rien à voir.

1. Ton code nécessite de passer à la poo. Sinon, c'est le mur ou difficilement maintenable. Si toutefois, tu ne te sens pas capable de coder à l'objet, VueJS/SvelteJS/ReactJS/BackboneJS/etc. sont là pour ce genre de choses entres autres.
2. commente mieux ton code
3. choisi des noms de variables plus adéquates
4. <label> c'est pas déconnant
Modifié par niuxe (07 Feb 2021 - 16:06)
Modérateur
Salut,

Je crois que tu t'es un peu compliqué la tache au fur et a mesure que tu avances... Tout passe par le Js du coup c'est hyper compliqué a suivre le fil... pourquoi générer les input via Js au lieu de tout mettre dans le DOM ? Normalement coté Js tu n'aurais qu'a mettre des eventListner et a agir en fonction du comportement normal. Ici par exemple tu fait ça :
function sel(y) {
	//x = y.closest('tr');
	if (y.checked) {
		//x.style.background = "#8af";
		y.setAttribute('checked', '');

Pourquoi faire un y.setAttribute('checked', '') alors que y est déjà checked naturellement ?
Du coup ta fonction sel se résume juste à changer le style de la ligne ?

Je n'ai pas réussi à comprendre comment tu gères les options cochées ou pas dans le tri du ton tableau... a quel moment tu les fait passer en priorité ?

Et sinon pourquoi passer par les setAttribute / remove attribute plutot que par .checked = false / true ?

Un truc dans ce gout là quoi :
<buton id="reset">reset</buton>
<table>
  <tr>
    <td><input type="checkbox"></td>
    <td>coucou</td>
  </tr>
  <tr>
    <td><input type="checkbox"></td>
    <td>coucou</td>
  </tr>
  <tr>
    <td><input type="checkbox"></td>
    <td>coucou</td>
  </tr>
  <tr>
    <td><input type="checkbox"></td>
    <td>coucou</td>
  </tr>
</table>

var checboxes = document.querySelectorAll('input[type=checkbox]');

checboxes.forEach(function (el) {
  el.addEventListener("click", function () {
    setStyle(el);
  }, false);
});

function setStyle(el) {
	el.closest('tr').classList.toggle('checked');
}

var reset = document.getElementById('reset');
reset.addEventListener("click", uncheckAll, false);

function uncheckAll() {
  var allselected = document.querySelectorAll('input:checked');
  allselected.forEach(e => {
    e.checked = false;
    setStyle(e);
  });
}

https://jsfiddle.net/undless/fq7exp9s/

Pas de DOM généré et coté JS des listner pour repérer les click et juste des test sur les états naturels. Je pense que le fait que tu gère ca coté Js en plus du DOM qui le fait naturellement ca brouille un peu les piste..

Apres faut bien sur venir greffer le tri mais au moment du click sur le tri tu récupère tout les input checked pour les mettre en priorité etc.

Que les autres membres du Forum m'arrête si je dis des bêtises hein Smiley sweatdrop mais c'est plutôt comme ca que j'ai tendance a l'aborder. [EDIT]-> Ah bah Niuxe est là on est sauvé Smiley biggrin [/EDIT]
Modifié par _laurent (07 Feb 2021 - 16:09)
Modérateur
_laurent a écrit :
Ah bah Niuxe est là on est sauvé

oui nid iou Smiley lol Smiley lol

_laurent a écrit :

Je crois que tu t'es un peu compliqué la tache au fur et a mesure que tu avances... Tout passe par le Js du coup c'est hyper compliqué a suivre le fil... pourquoi générer les input via Js au lieu de tout mettre dans le DOM ? Normalement coté Js tu n'aurais qu'a mettre des eventListner et a agir en fonction du comportement normal.

+1 C'est pour ça que je n'ai pas continué à lire le code. Pour moi, ce n'est pas du tout pertinent de créer un event pour ça.

toujours, toujours, toujours, toujours, toujours, toujours .... faire simple surtout si aborde ce genre de sujet/cas

_laurent a écrit :

Pas de DOM généré et coté JS des listner pour repérer les click et juste des test sur les états naturels. Je pense que le fait que tu gère ca coté Js en plus du DOM qui le fait naturellement ca brouille un peu les piste..

Apres faut bien sur venir greffer le tri mais au moment du click sur le tri tu récupère tout les input checked pour les mettre en priorité etc.

Que les autres membres du Forum m'arrête si je dis des bêtises hein Smiley sweatdrop mais c'est plutôt comme ca que j'ai tendance a l'aborder.

mettre en premier les checkbox cochées, mmmh ça complexifie alors que ce n'est pas vraiment le cas.

@Jerome87
Comment je procéderai ?
- Dans un array, je placerai des objets litéraux/statiques (ça c'est ma collection de modèles)
- dans chaque objet litéral, j'insèrerai clef et valeur. exemple de lignes :
[
    {
        "id"        : 1,
        "checked"   : false,
        "name"      : "Accès du périphérique d'interface utilisateur",
        "state"     : "Démarré",
        "starting"  : "Désactivé"
    },
    {
        "id"        : 2,
        "checked"   : false,
        "name"      : "Appel de procédure distante (RPC)",
        "state"     : "",
        "starting"  : "Manuel"
    }, 
//etc
]

- au chargement de la page, j'insère ce array dans un <table> (la vue)
- chaque bouton ou champ a son propre controlleur. Chaque action donnera une mise à jour dans la collection.
- Chaque changement, vider la vue et la remplacer par la collection modifiée

Si tu travailles en procédural, tes controlleurs sont de petites fonctions que tu rattaches à tes boutons
Si tu travailles à l'objet, tu crées un objet app qui à l'intérieur de celui ci va avoir plusieurs dépendances (le minimum est : tes models/ta collection/tes controlleurs/ta vue). J'ai bien dit le minimum. Parce qu'à priori, j'en vois plus en fait (une collection avec un model, un controleur avec plusieurs sous controleurs, plusieurs objets qui vont gérer l'architecture de l'app (state par exemple)).

Bien que je sois de moins en moins adepte de jQuery (voir plus du tout), je t'invite à t'inspirer de la logique de travail appliquée de Jeremy Ashkenas. C'est un solution parmi tant d'autres.
Modifié par niuxe (07 Feb 2021 - 17:26)
Merci pour vos réponses.
Mon niveau en javascript est bien trop faible pour que j'arrive à faire quelque chose de propre et correct.
J'arrive juste à bricoler.
Mon code tourne en local, je ne prévois pas de le mettre sur un site.

@niuxe : je n'ai pas vu le bug au niveau du trie.

@_laurent : En fait j'ajoutais le paramètre checked car il y avait un bug, quand je cliquais sur la case elle ne se cocher pas. Maintenant tous va bien de ce côté.
Maintenant j'ajoute une value 0 car la fonction de trie la prend en compte en utilisant innerHTML au lieu de TextContent :
const tdVal = (row, ids) => row.children[ids].innerHTML,


function sel(y) {
	x = y.closest('tr');
	if (y.checked) {
		x.style.background = "#8af";
		y.value = 0
	} else {
		x.style.background = "";
		y.value = 1
	}
}


Ensuite pour les cases à cocher, je les ajoute via javascript car je veut garder le fichier html le plus alléger. Le fichier sera destiné à être utilisé dans d'autres situations et par des personnes qui ne connaissent pas le codage. Je n'aurais qu'a leur dire ou écrire leurs données.

Là le fichier fonctionne correctement en locale.

J'aimerais bien suivre et savoir mettre en pratique tous vos conseils mais je bien trop mauvais en javascript.

Merci pour toutes vos réponses.

Cordialement
Jérôme

Ci-joint le code complet du fichier :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Services inutiles</title>
<style>
* {font-family: "Fira Sans", sans-serif}
input[type='checkbox'] {filter: hue-rotate(20deg)}
table {
	border-collapse: collapse;
	margin: -7px auto
}
th, td, #bt {padding: 2px 4px}
th, #bt {color: #fff}
th {background: #5d625c}
#l1 {text-align: right}
#l1, #t2 {color: #c6c3bd}
#bx, tr:nth-child(odd) {background: #dddad4}
#bx {
	color: blue;
	width: 105px;
	outline: 0
}
#t2, #nb {position: absolute}
tr {color: #444}
tr:nth-child(even) {background: #c6c3bd}
#bt {
	border-radius: 2px;
	text-decoration: none;
	font-size: 12px;
	background: blue;
	box-shadow: inset 2px 2px 3px #88f, inset -2px -2px 2px #13a;
	margin-left: 2px
}
#bt:active {color: #ff0}
span {
	font-size: 9px;
	bottom: 3px;
	margin: 0 5px;
	position: relative
}
#nb {margin-left: 34px}
#a, #nb {width: 434px}
#nb {
	text-align: center;
	color: lime
}
</style>
</head>
<body>
<table>
<thead>
<tr><th id="l1" colspan="4"><div id="nb"></div>Rechercher : <input id="bx" type="text"/><a href id="bt" onclick="vide()">?</a></th></tr>
<tr><th id="a"><div id="t2">Trier :</div><span>?</span>Nom du service<span>?</span></th>
<th id="b"><span>?</span>Etat<span>?</span></th>
<th id="c"><span>?</span>Démarrage<span>?</span></th></tr>
</thead>
<tbody id="tb">
<tr><td>Accès du périphérique d'interface utilisateur</td><td></td><td>Désactivé</td></tr>
<tr><td>Acquisition d'image Windows (WIA)</td><td></td><td>Manuel</td></tr>
<tr><td>Agent de protection d’accès réseau</td><td></td><td>Désactivé</td></tr>
<tr><td>Agent de stratégie IPsec</td><td>Démarré</td><td>Manuel</td></tr>
<tr><td>Alimentation</td><td>Démarré</td><td>Automatique</td></tr>
<tr><td>Appel de procédure distante (RPC)</td><td>Démarré</td><td>Automatique</td></tr>
<tr><td>Application Host Helper Service</td><td></td><td>Automatique</td></tr>
<tr><td>Application système COM+</td><td></td><td>Manuel</td></tr>
<tr><td>Assistance IP</td><td></td><td>Désactivé</td></tr>
<tr><td>Assistance NetBIOS sur TCP/IP</td><td></td><td>Désactivé</td></tr>
<tr><td>Audio Windows</td><td>Démarré</td><td>Automatique</td></tr>
<tr><td>BranchCache</td><td></td><td>Désactivé</td></tr>
<tr><td>Brillance adaptative</td><td></td><td>Désactivé</td></tr>
</tbody>
</table>
</body>
<script>
var clik = 0,
	myBox = document.getElementById("bx"),
	nb = document.getElementById("nb");
function sel(y) {
	x = y.closest('tr');
	if (y.checked) {
		x.style.background = "#8af";
		y.value = 0
	} else {
		x.style.background = "";
		y.value = 1
	}
}
function stylraz(raz) {
	nb.innerHTML = "";
	f0 = document.querySelectorAll("span, #t2");
	for (var a = 0; a < f0.length; a++) {
		f0[a].style.color = "";
		if(raz == 1) {f0[a].innerHTML = f0[a].innerHTML.replace("?","?")}
	}
}
//Tri
const compar = (ids, asc) => (row1, row2) => {
	const	tdVal = (row, ids) => row.children[ids].innerHTML,
			tri = (v1, v2) => v1 !== '' && v2 !== '' && !isNaN(v1, v2) ? v1 - v2 : v1.toString().localeCompare(v2);
	return tri(tdVal(asc ? row1 : row2, ids), tdVal(asc ? row2 : row1, ids));
};
const tbx = document.getElementById('tb'),
	thx = document.querySelectorAll('#a, #b, #c'),
	trx = tbx.querySelectorAll('tr');
thx.forEach(tht => tht.addEventListener('click', () => {
	//Filtrea0
	v = tbx.querySelectorAll('#z').length;
	for (var b = 1; b <= v; b++) {document.getElementById('z').remove()}
	//Filtrea0
	myBox.value="";
	let classe = Array.from(trx).sort(compar(Array.from(thx).indexOf(tht), this.asc = !this.asc));
	//Style et Flèche
	if (clik == 1) {r1 = '?', r2 = '?', clik = 0}
	else {r1 = '?', r2 = '?', clik = 1}
	tht.innerHTML = tht.innerHTML.replaceAll(r1,r2);
	stylraz(0);
	document.getElementById("t2").style.color = "lime";
	w = tht.querySelectorAll("span");
	for (var c = 0; c < w.length; c++) {w[c].style.color = "lime"}
	//Fin Style...
	classe.forEach(tr => tbx.appendChild(tr));
}));
//Tri
//Filtre
for (var d = 0; d < trx.length; d++) {trx[d].querySelector('td').insertAdjacentHTML('afterbegin', '<input type="checkbox" onclick="sel(this)" value="1"> ')}
document.addEventListener('DOMContentLoaded', function () {
	const Tab = document.getElementById('tb');
	let Tab1 = [];
	for (let e = 0; e < Tab.rows.length; e++) {
		Tab1[e] = [];
		const objCells = Tab.rows.item(e).cells;
		for (let f = 0; f < objCells.length; f++) {Tab1[e][f] = objCells.item(f).innerHTML}
	}
	document.getElementById("bx").addEventListener('input', event => {
		const caseVal = document.getElementById("bx").value;
		if (caseVal.length > 0){stylraz(1)}
		if (caseVal != '' || caseVal != 'undefined') {
			Tab.innerHTML = "";
			let Tab2 = [];
			for (let g = 0; g < Tab1.length; g++) {
				z = Tab1[g];
				for (let h = 0; h < 3; h++) {Tab2[h] = z[h].toLowerCase().indexOf(caseVal.toLowerCase())}
				if (Tab2[0] > -1 || Tab2[1] > -1 || Tab2[2] > -1) {Tab.innerHTML += '<tr id="z"><td>'+z[0]+'</td><td>'+z[1]+'</td><td>'+z[2]+'</td></tr>'}
			}
		nb.innerHTML = tbx.querySelectorAll('#z').length+" résultat(s) trouvé(s)";
		}
	});
});
//Filtre
function vide() {
	var myBoxEven = new Event('input',{bubbles:true,cancelable: true});
	myBox.value="";
	myBox.dispatchEvent(myBoxEven);
	stylraz(1)
}
</script>
</html>

Modifié par Jerome87 (09 Feb 2021 - 01:36)
Modérateur
Bonjour,

Jerome87 a écrit :
Mon niveau en java...


Merci d'écrire "Mon niveau en javascript..." Smiley cligne

Java est un autre langage qui n'a rien à voir avec javascript.

Amicalement,
Modérateur
niuxe a écrit :
mettre en premier les checkbox cochées, mmmh ça complexifie alors que ce n'est pas vraiment le cas.

Ah il me semblait que c'était le cas dans son code en fait quand on triait et qu'on avait coché des lignes différentes et le bug c'était que quand on décochait elles restaient en top priorité.


parsimonhi a écrit :
Merci d'écrire "Mon niveau en javascript..." Smiley cligne
Java est un autre langage qui n'a rien à voir avec javascript.

Ah je voulais le mettre dans ma réponse et j'ai zappé !

@Jerome87 sinon tu peux juste écrire "Js" c'est encore plus court et ca reste correct ^^

Bonne journée à tous
Ah oui effectivement, une mauvaise habitude de raccourcir les mots.
J'ai corrigé ces erreurs.

Sinon niuxe tu avais raison pour le mur.
Fier de moi j'avais réussit a créer sur les 2 dernières colonnes des listes déroulante.
Elle fonctionnent bien mais du coup il y a un autre bug.

Donc le plus sage est rester là.