11521 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous,

J'ai un besoin particulier pour effectuer un tri un peu spécial. En effet, le tri sur un tableau c'est pas ce qu'il y a de plus complexe, sauf quand on veux y ajouter des exceptions de tri sur ce tableau.
Pour faire bref, mon tableau comporte X nombre de ligne (générée depuis un foreach coté compilation serveur), chaque ligne de ce tableau est un "objet", et chacun de ces objets disposent de sous objet qui leurs sont propre.

Pour que ce soit plus simple à comprendre, voici un bout de code


Tableau - Objet Parent

<table id='idArray'>

<thead><tr><th>Col1</th><th>Col2</th>Col3</th><th>Col4</th><th>Col5</th></tr></thead>

<tbody>

<tr><td>Val1Obj1</td><td>Val2Obj1</td><td>Val3Obj1</td><td>Val4Obj1</td><td>Val5Obj1</td></tr>
<tr><td>Val1Obj2</td><td>Val2Obj2</td><td>Val3Obj2</td><td>Val4Obj2</td><td>Val5Obj2</td></tr>
<tr><td>Val1Obj3</td><td>Val2Obj3</td><td>Val3Obj3</td><td>Val4Obj3</td><td>Val5Obj3</td></tr>

</tbody>
</table>


Tableau - Objet Parent avec Enfant (intégré à la compilation coté serveur, il n'y à qu'un seul tableau hein)

<table id='idArray'>

<thead><tr><th>Col1</th><th>Col2</th>Col3</th><th>Col4</th><th>Col5</th></tr></thead>

<tbody>

<tr><td>Val1Obj1</td><td>Val2Obj1</td><td>Val3Obj1</td><td>Val4Obj1</td><td>Val5Obj1</td></tr>
<tr><td>Val1Obj1Enf1</td><td>Val2Obj1Enf1</td><td>Val3Obj1Enf1</td><td>Val4Obj1Enf1</td><td>Val5Obj2Enf1</td></tr>

<tr><td>Val1Obj2</td><td>Val2Obj2</td><td>Val3Obj2</td><td>Val4Obj2</td><td>Val5Obj2</td></tr>
<tr><td>Val1Obj2Enf1</td><td>Val2Obj2Enf1</td><td>Val3Obj2Enf1</td><td>Val4Obj2Enf1</td><td>Val5Obj1Enf1</td></tr>
<tr><td>Val1Obj2Enf2</td><td>Val2Obj2Enf2</td><td>Val3Obj2Enf2</td><td>Val4Obj2Enf2</td><td>Val5Obj1Enf2</td></tr>

<tr><td>Val1Obj3</td><td>Val2Obj3</td><td>Val3Obj3</td><td>Val4Obj3</td><td>Val5Obj3</td></tr>
<tr><td>Val1Obj3Enf1</td><td>Val2Obj3Enf1</td><td>Val3Obj3Enf1</td><td>Val4Obj3Enf1</td><td>Val5Obj3Enf1</td></tr>
<tr><td>Val1Obj3Enf2</td><td>Val2Obj3Enf2</td><td>Val3Obj3Enf2</td><td>Val4Obj3Enf2</td><td>Val5Obj3Enf2</td></tr>
<tr><td>Val1Obj3Enf3</td><td>Val2Obj3Enf3</td><td>Val3Obj3Enf3</td><td>Val4Obj3Enf3</td><td>Val5Obj3Enf3</td></tr>

</tbody>
</table>


Pour résumer, nous avons tout nos objets dans le tableau, mais je détermine que certain objet (<tr>) sont des enfants d'autres objet (<tr>).

Légende:
Ligne TR qui contient explicitement "ValXObjX" est un parent
Ligne TR qui contient "EnfX" est un enfant du parent "ObjX" qui est contenu

Note: les valeurs sont faites pour l'exemple, dans la production, ce code ne ressemble absolument pas à ça, du moins, pas le contenu du tableau, nous ne pouvons donc pas nous baser dessus. A défaut, seul le contenu de la première colonne des parents/enfants est le même (identifiant unique).

Si on tri simplement, en ASC c'est OK mais en DESC l'enfant se retrouve au dessus du Parent, dans la théorie du tri ce comportement est normal mais dans cette pratique, il ne doit pas avoir lieu.

Peux importe le type de tri, ASC ou DESC, l'enfant doit toujours être en dessous du parent. en prenant en compte les autres parents enfants.

Avez-vous déjà été confronté à ceci ?
Vers quel techno me conseillez-vous de chercher ?

Par avance merci,
NotFound
Salut

J'ai jamais été confronté à ça.. mais en Js je suis sur que tu trouvera ton bonheur.

Moi j'utilise une méthode qui me tri entièrement ma <table> donc ce n'est pas ce que tu cherche mais peut etre en jetant un coup d'oeil tu aura LA réponse

la fonction peut trier du numérique, de l'alpha et de l'alphanumérique

function sortTable(tid, col, ord){ 
	var mybody = $("#"+tid).children('tbody'),
		lines = mybody.children('tr'),
		sorter = [],
		i = -1,
		j = -1;
 
	while(lines[++i]){
		sorter.push([lines.eq(i), lines.eq(i).children('td').eq(col).text()])
	}
 
	if (ord == 'asc') {
		sorter.sort(function(a, b){
			var c1 = replaceSpec(a[1]),
				c2 = replaceSpec(b[1]);
 
			if (c1 > c2){
				return 1;
			} else if(c1 < c2){
				return -1;
			} else {
				return 0;
			}
		});
	} else if (ord == 'desc') {
		sorter.sort(function(a, b){
			var c1 = replaceSpec(a[1]),
				c2 = replaceSpec(b[1]);
 
			if (c1 > c2){
				return -1;
			} else if(c1 < c2){
				return 1;
			} else {
				return 0;
			}
		});
	} else if (ord == 'nasc'){
		sorter.sort(function(a, b){return(a[1] - b[1]);});
	} else if (ord == 'ndesc'){
		sorter.sort(function(a, b){return(b[1] - a[1]);});
	} else if (ord == '?asc'){
		sorter.sort(function(a, b){
			var x = parseInt(a[1], 10),
				y = parseInt(b[1], 10),
				c1 = replaceSpec(a[1]),
				c2 = replaceSpec(b[1]);
 
			if (isNaN(x) || isNaN(y)){
				if (c1 > c2){
					return 1;
				} else if(c1 < c2){
					return -1;
				} else {
					return 0;
				}
			} else {
				return(a[1] - b[1]);
			}
		});
	} else if (ord == '?desc'){
		sorter.sort(function(a, b){
			var x = parseInt(a[1], 10),
				y = parseInt(b[1], 10),
				c1 = replaceSpec(a[1]),
				c2 = replaceSpec(b[1]);
 
			if (isNaN(x) || isNaN(y)){
				if (c1 > c2){
					return -1;
				} else if(c1 < c2){
					return 1;
				} else {
					return 0;
				}
			} else {
				return(b[1] - a[1]);
			}
		});
	}
 
	while(sorter[++j]){
		mybody.append(sorter[j][0]);
	}
}


<div>
<p>Alphabétique<br/>colonne 1</p>
<input type="button" onclick="sortTable('matable',0, 'desc')" value="tri desc col 1" />
<input type="button" onclick="sortTable('matable',0, 'asc')" value="tri asc col1" /><br/>
 
<input type="button" onclick="sortTable('matable',0, 'ndesc')" value="tri num desc col 1" />
<input type="button" onclick="sortTable('matable',0, 'nasc')" value="tri num asc col1" /><br/>
 
<input type="button" onclick="sortTable('matable',0, '?desc')" value="tri alphanum desc col 1" />
<input type="button" onclick="sortTable('matable',0, '?asc')" value="tri alphanum asc col1" />
 
<p>colonne 2</p>
<input type="button" onclick="sortTable('matable',1, 'desc')" value="tri desc col2" />
<input type="button" onclick="sortTable('matable',1, 'asc')" value="tri asc col2" /><br/>
 
<input type="button" onclick="sortTable('matable',1, 'ndesc')" value="tri num desc col2" />
<input type="button" onclick="sortTable('matable',1, 'nasc')" value="tri num asc col2" /><br/>
 
<input type="button" onclick="sortTable('matable',1, '?desc')" value="tri alphanum desc col2" />
<input type="button" onclick="sortTable('matable',1, '?asc')" value="tri alphanum asc col2" />
</div>

Modifié par JENCAL (18 Aug 2015 - 16:44)
Salut JenCal et merci pour ta réponse.

Cependant ton code ne correspond pas à mon besoin.

A oui, j'ai oublié de vous dire, par défaut, les enfants sont masqués ! Il faut cliquer sur un lien contenu dans une colonne de Parent pour que son/ses enfants s'affiche (erase display:none).

J'ai pensé à faire l'intégration des enfants en Ajax sur le tableau.
Chargement de la page root, nous avons donc la liste des parents.
Lors du clique sur le lien contenu sur un des parents, ceci envoi une requête asynchrone pour récupérer les enfants du parent, puis les afficher directement sous le parent qui à initié cet instance en collant simplement un 'this.id' lors de l'initiation pour permettre l'import du dom à l’endroit désiré.
Cependant, cette solution est bien mais à une faille ! Une fois l'enfant affiché (après avoir trié comme on le voulais), si on effectue un tri ASC pas de soucis, mais le DESC, Oui, problème, l'enfant se retrouve à nouveau au dessus de son parent. Voir pire selon les tris... Les enfants se choisissent un autre parent (tout dépends des contenus des autres colonne ce comportement).

Donc j'ai pas continuer vers cette solution.

Wait&See

Par avance merci,
NotFound
La solution la plus simple à mon avis, est de modifier ton tableau et de le diviser en plusieurs <tbody> distincts. Ce n'est absolument pas interdit d'avoir plusieurs corps de tableau <tbody> pour le même tableau. Seul le <thead> doit être unique et le premier enfant de <table> hors <caption>.

Ensuite, tu modifies ton script de tri pour ne déplacer que les <tbody> les uns par rapport aux autres. Ainsi ce qui doit rester groupé le restera, quelque soit l'ordre dans lequel tu réordonnes les <tbody>.

Toutes les autres solutions tentant bien que mal d'ignorer des lignes ou d'en déplacer plusieurs à la fois risquent de s'avérer beaucoup plus complexes et moins maintenables.
Administrateur
Bonjour et bienvenue, Smiley smile

tu dois trier les parents et faire suivre les enfants tels quels après leur parent respectif, en ne changeant surtout pas l'ordre des enfants, c'est ça ?
Question préliminaire : ils sont longs comment tes tableaux ? 10, 100, 1000 ou plus de lignes ?
Bonjour et désolé de cette réponse tardive.

@Felipe :
Oui dans un premier temps mes parents doivent être triés (asc ou desc), mais cela fonctionne.
Cepandant, j'ai les enfants qui remontent au dessus des parents lors du tri DESC, ce qui en soit est tout à fait normal.

Par ailleurs, ce problème est fixé.

Lors du tri initial (asou desc) j'agis comme suit (version synthétique):
- Je sais maintenant identifier le parent d'un enfant donc :
- enfants.remove() sur tous les enfants
- parent.after(enfant.outerHTML)

=> Le problème venait simplement du fait que je n'avais pas de correspondance entre un parent et ses enfants. Merci l'ajour d'une classe pour les parents et d'un id type :
- parent id = numeroParent
- enfant id = numeroParent+numeroEnfant

Ce qui lors d'une recherche, si je match l'ID du parent dans l'enfant c'est donc un enfant direct, je peux donc l'afficher au bon endroit, en somme directement sous son parent.

:)